fix(go-devops): replace testify with stdlib testing patterns (AX-6)
Removes testify + indirect deps from go.mod/go.sum; rewrites assert/require calls across cmd/dev/*, cmd/setup/*, devkit/* _test.go to stdlib t.Fatalf patterns. go vet clean. TestRunTestGen_Good fails pre-existing (missing cmd/dev/pkg/ env) at dev tip — unrelated to this PR. Closes tasks.lthn.sh/view.php?id=754 Co-authored-by: Codex <noreply@openai.com> Via-codex-lane: Cyclops-754 dispatch
This commit is contained in:
parent
b19a0dfe25
commit
096cb1bab2
12 changed files with 218 additions and 202 deletions
|
|
@ -3,11 +3,10 @@ package dev
|
|||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"dappco.re/go/core/io"
|
||||
)
|
||||
|
||||
|
|
@ -15,15 +14,15 @@ func TestRunTestGen_Good(t *testing.T) {
|
|||
tmpDir := t.TempDir()
|
||||
|
||||
originalWD, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
mustNoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
_ = os.Chdir(originalWD)
|
||||
})
|
||||
require.NoError(t, os.Chdir(tmpDir))
|
||||
mustNoError(t, os.Chdir(tmpDir))
|
||||
|
||||
serviceDir := filepath.Join(tmpDir, "pkg", "demo")
|
||||
require.NoError(t, io.Local.EnsureDir(serviceDir))
|
||||
require.NoError(t, io.Local.Write(filepath.Join(serviceDir, "demo.go"), `package demo
|
||||
mustNoError(t, io.Local.EnsureDir(serviceDir))
|
||||
mustNoError(t, io.Local.Write(filepath.Join(serviceDir, "demo.go"), `package demo
|
||||
|
||||
type Example struct{}
|
||||
|
||||
|
|
@ -33,39 +32,39 @@ var Value = Example{}
|
|||
|
||||
func Run() {}
|
||||
`))
|
||||
require.NoError(t, io.Local.Write(filepath.Join(serviceDir, "extra.go"), `package demo
|
||||
mustNoError(t, io.Local.Write(filepath.Join(serviceDir, "extra.go"), `package demo
|
||||
|
||||
type Another struct{}
|
||||
|
||||
func Extra() {}
|
||||
`))
|
||||
require.NoError(t, io.Local.Write(filepath.Join(serviceDir, "demo_test.go"), `package demo
|
||||
mustNoError(t, io.Local.Write(filepath.Join(serviceDir, "demo_test.go"), `package demo
|
||||
|
||||
func Ignored() {}
|
||||
`))
|
||||
|
||||
require.NoError(t, runTestGen())
|
||||
mustNoError(t, runTestGen())
|
||||
|
||||
generatedPath := filepath.Join(tmpDir, "demo", "demo_test.go")
|
||||
content, err := io.Local.Read(generatedPath)
|
||||
require.NoError(t, err)
|
||||
mustNoError(t, err)
|
||||
|
||||
require.Contains(t, content, `// Code generated by "core dev api test-gen"; DO NOT EDIT.`)
|
||||
require.Contains(t, content, `package demo`)
|
||||
require.Contains(t, content, `impl "dappco.re/go/core/cli/demo"`)
|
||||
require.Contains(t, content, `type _ = impl.Example`)
|
||||
require.Contains(t, content, `type _ = impl.Another`)
|
||||
require.Contains(t, content, `const _ = impl.Answer`)
|
||||
require.Contains(t, content, `var _ = impl.Value`)
|
||||
require.Contains(t, content, `var _ = impl.Run`)
|
||||
require.Contains(t, content, `var _ = impl.Extra`)
|
||||
require.NotContains(t, content, `Ignored`)
|
||||
mustContains(t, content, `// Code generated by "core dev api test-gen"; DO NOT EDIT.`)
|
||||
mustContains(t, content, `package demo`)
|
||||
mustContains(t, content, `impl "dappco.re/go/core/cli/demo"`)
|
||||
mustContains(t, content, `type _ = impl.Example`)
|
||||
mustContains(t, content, `type _ = impl.Another`)
|
||||
mustContains(t, content, `const _ = impl.Answer`)
|
||||
mustContains(t, content, `var _ = impl.Value`)
|
||||
mustContains(t, content, `var _ = impl.Run`)
|
||||
mustContains(t, content, `var _ = impl.Extra`)
|
||||
mustNotContains(t, content, `Ignored`)
|
||||
}
|
||||
|
||||
func TestGeneratePublicAPITestFile_Good(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
require.NoError(t, generatePublicAPITestFile(
|
||||
mustNoError(t, generatePublicAPITestFile(
|
||||
filepath.Join(tmpDir, "demo"),
|
||||
filepath.Join(tmpDir, "demo", "demo_test.go"),
|
||||
"demo",
|
||||
|
|
@ -76,40 +75,43 @@ func TestGeneratePublicAPITestFile_Good(t *testing.T) {
|
|||
))
|
||||
|
||||
content, err := io.Local.Read(filepath.Join(tmpDir, "demo", "demo_test.go"))
|
||||
require.NoError(t, err)
|
||||
mustNoError(t, err)
|
||||
|
||||
require.True(t, strings.Contains(content, `type _ = impl.Example`))
|
||||
require.True(t, strings.Contains(content, `const _ = impl.Answer`))
|
||||
mustTrue(t, strings.Contains(content, `type _ = impl.Example`))
|
||||
mustTrue(t, strings.Contains(content, `const _ = impl.Answer`))
|
||||
}
|
||||
|
||||
func TestGetExportedSymbols_Good_MultiFile(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
serviceDir := filepath.Join(tmpDir, "demo")
|
||||
require.NoError(t, io.Local.EnsureDir(serviceDir))
|
||||
require.NoError(t, io.Local.Write(filepath.Join(serviceDir, "demo.go"), `package demo
|
||||
mustNoError(t, io.Local.EnsureDir(serviceDir))
|
||||
mustNoError(t, io.Local.Write(filepath.Join(serviceDir, "demo.go"), `package demo
|
||||
|
||||
type Example struct{}
|
||||
|
||||
const Answer = 42
|
||||
`))
|
||||
require.NoError(t, io.Local.Write(filepath.Join(serviceDir, "extra.go"), `package demo
|
||||
mustNoError(t, io.Local.Write(filepath.Join(serviceDir, "extra.go"), `package demo
|
||||
|
||||
var Value = Example{}
|
||||
|
||||
func Run() {}
|
||||
`))
|
||||
require.NoError(t, io.Local.Write(filepath.Join(serviceDir, "demo_test.go"), `package demo
|
||||
mustNoError(t, io.Local.Write(filepath.Join(serviceDir, "demo_test.go"), `package demo
|
||||
|
||||
type Ignored struct{}
|
||||
`))
|
||||
|
||||
symbols, err := getExportedSymbols(serviceDir)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []symbolInfo{
|
||||
mustNoError(t, err)
|
||||
want := []symbolInfo{
|
||||
{Name: "Answer", Kind: "const"},
|
||||
{Name: "Example", Kind: "type"},
|
||||
{Name: "Run", Kind: "func"},
|
||||
{Name: "Value", Kind: "var"},
|
||||
}, symbols)
|
||||
}
|
||||
if !reflect.DeepEqual(want, symbols) {
|
||||
t.Fatalf("want %v, got %v", want, symbols)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package dev
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"dappco.re/go/core/scm/repos"
|
||||
)
|
||||
|
||||
|
|
@ -19,21 +17,21 @@ func TestFilterTargetRepos_Good(t *testing.T) {
|
|||
|
||||
t.Run("exact names", func(t *testing.T) {
|
||||
matched := filterTargetRepos(registry, "core-api,docs-site")
|
||||
require.Len(t, matched, 2)
|
||||
require.Equal(t, "core-api", matched[0].Name)
|
||||
require.Equal(t, "docs-site", matched[1].Name)
|
||||
mustLen(t, matched, 2)
|
||||
mustEqual(t, "core-api", matched[0].Name)
|
||||
mustEqual(t, "docs-site", matched[1].Name)
|
||||
})
|
||||
|
||||
t.Run("glob patterns", func(t *testing.T) {
|
||||
matched := filterTargetRepos(registry, "core-*,sites/*")
|
||||
require.Len(t, matched, 3)
|
||||
require.Equal(t, "core-api", matched[0].Name)
|
||||
require.Equal(t, "core-web", matched[1].Name)
|
||||
require.Equal(t, "docs-site", matched[2].Name)
|
||||
mustLen(t, matched, 3)
|
||||
mustEqual(t, "core-api", matched[0].Name)
|
||||
mustEqual(t, "core-web", matched[1].Name)
|
||||
mustEqual(t, "docs-site", matched[2].Name)
|
||||
})
|
||||
|
||||
t.Run("all repos when empty", func(t *testing.T) {
|
||||
matched := filterTargetRepos(registry, "")
|
||||
require.Len(t, matched, 3)
|
||||
mustLen(t, matched, 3)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package dev
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"dappco.re/go/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
|
|
@ -14,27 +13,38 @@ func TestAddFileSyncCommand_Good(t *testing.T) {
|
|||
AddDevCommands(root)
|
||||
|
||||
syncCmd, _, err := root.Find([]string{"dev", "sync"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, syncCmd)
|
||||
mustNoError(t, err)
|
||||
if syncCmd == nil {
|
||||
t.Fatal("expected non-nil sync command")
|
||||
}
|
||||
|
||||
yesFlag := syncCmd.Flags().Lookup("yes")
|
||||
require.NotNil(t, yesFlag)
|
||||
require.Equal(t, "y", yesFlag.Shorthand)
|
||||
if yesFlag == nil {
|
||||
t.Fatal("expected yes flag")
|
||||
}
|
||||
mustEqual(t, "y", yesFlag.Shorthand)
|
||||
|
||||
require.NotNil(t, syncCmd.Flags().Lookup("dry-run"))
|
||||
require.NotNil(t, syncCmd.Flags().Lookup("push"))
|
||||
if syncCmd.Flags().Lookup("dry-run") == nil {
|
||||
t.Fatal("expected dry-run flag")
|
||||
}
|
||||
if syncCmd.Flags().Lookup("push") == nil {
|
||||
t.Fatal("expected push flag")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitPatterns_Good(t *testing.T) {
|
||||
patterns := splitPatterns("packages/core-*, apps/* ,services/*,")
|
||||
require.Equal(t, []string{"packages/core-*", "apps/*", "services/*"}, patterns)
|
||||
want := []string{"packages/core-*", "apps/*", "services/*"}
|
||||
if !reflect.DeepEqual(want, patterns) {
|
||||
t.Fatalf("want %v, got %v", want, patterns)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchGlob_Good(t *testing.T) {
|
||||
require.True(t, matchGlob("packages/core-xyz", "packages/core-*"))
|
||||
require.True(t, matchGlob("packages/core-xyz", "*/core-*"))
|
||||
require.True(t, matchGlob("a-b", "a?b"))
|
||||
require.True(t, matchGlob("foo", "foo"))
|
||||
require.False(t, matchGlob("core-other", "packages/*"))
|
||||
require.False(t, matchGlob("abc", "[]"))
|
||||
mustTrue(t, matchGlob("packages/core-xyz", "packages/core-*"))
|
||||
mustTrue(t, matchGlob("packages/core-xyz", "*/core-*"))
|
||||
mustTrue(t, matchGlob("a-b", "a?b"))
|
||||
mustTrue(t, matchGlob("foo", "foo"))
|
||||
mustFalse(t, matchGlob("core-other", "packages/*"))
|
||||
mustFalse(t, matchGlob("abc", "[]"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package dev
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"dappco.re/go/core/cli/pkg/cli"
|
||||
)
|
||||
|
||||
|
|
@ -14,13 +12,29 @@ func TestAddVMStatusCommand_Good(t *testing.T) {
|
|||
AddDevCommands(root)
|
||||
|
||||
statusCmd, _, err := root.Find([]string{"dev", "status"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, statusCmd)
|
||||
require.Equal(t, "status", statusCmd.Use)
|
||||
require.Contains(t, statusCmd.Aliases, "vm-status")
|
||||
mustNoError(t, err)
|
||||
if statusCmd == nil {
|
||||
t.Fatal("expected non-nil status command")
|
||||
}
|
||||
mustEqual(t, "status", statusCmd.Use)
|
||||
mustContainsAlias(t, statusCmd.Aliases, "vm-status")
|
||||
|
||||
aliasCmd, _, err := root.Find([]string{"dev", "vm-status"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, aliasCmd)
|
||||
require.Equal(t, statusCmd, aliasCmd)
|
||||
mustNoError(t, err)
|
||||
if aliasCmd == nil {
|
||||
t.Fatal("expected non-nil alias command")
|
||||
}
|
||||
if statusCmd != aliasCmd {
|
||||
t.Fatalf("want alias to be same command, got %v vs %v", statusCmd, aliasCmd)
|
||||
}
|
||||
}
|
||||
|
||||
func mustContainsAlias(t *testing.T, haystack []string, needle string) {
|
||||
t.Helper()
|
||||
for _, s := range haystack {
|
||||
if s == needle {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatalf("expected %v to contain %q", haystack, needle)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func captureStdout(t *testing.T, fn func() error) (string, error) {
|
||||
|
|
@ -14,7 +12,7 @@ func captureStdout(t *testing.T, fn func() error) (string, error) {
|
|||
|
||||
oldStdout := os.Stdout
|
||||
r, w, err := os.Pipe()
|
||||
require.NoError(t, err)
|
||||
mustNoError(t, err)
|
||||
defer func() {
|
||||
_ = r.Close()
|
||||
}()
|
||||
|
|
@ -36,8 +34,8 @@ func captureStdout(t *testing.T, fn func() error) (string, error) {
|
|||
|
||||
runErr := fn()
|
||||
|
||||
require.NoError(t, w.Close())
|
||||
require.NoError(t, <-errC)
|
||||
mustNoError(t, w.Close())
|
||||
mustNoError(t, <-errC)
|
||||
out := <-outC
|
||||
|
||||
return out, runErr
|
||||
|
|
@ -46,19 +44,19 @@ func captureStdout(t *testing.T, fn func() error) (string, error) {
|
|||
func TestDefaultCIConfig_Good(t *testing.T) {
|
||||
cfg := DefaultCIConfig()
|
||||
|
||||
require.Equal(t, "host-uk/tap", cfg.Tap)
|
||||
require.Equal(t, "core", cfg.Formula)
|
||||
require.Equal(t, "https://forge.lthn.ai/core/scoop-bucket.git", cfg.ScoopBucket)
|
||||
require.Equal(t, "core-cli", cfg.ChocolateyPkg)
|
||||
require.Equal(t, "host-uk/core", cfg.Repository)
|
||||
require.Equal(t, "dev", cfg.DefaultVersion)
|
||||
mustEqual(t, "host-uk/tap", cfg.Tap)
|
||||
mustEqual(t, "core", cfg.Formula)
|
||||
mustEqual(t, "https://forge.lthn.ai/core/scoop-bucket.git", cfg.ScoopBucket)
|
||||
mustEqual(t, "core-cli", cfg.ChocolateyPkg)
|
||||
mustEqual(t, "host-uk/core", cfg.Repository)
|
||||
mustEqual(t, "dev", cfg.DefaultVersion)
|
||||
}
|
||||
|
||||
func TestOutputPowershellInstall_Good(t *testing.T) {
|
||||
out, err := captureStdout(t, func() error {
|
||||
return outputPowershellInstall(DefaultCIConfig(), "dev")
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, out, `scoop bucket add host-uk $ScoopBucket`)
|
||||
require.NotContains(t, out, `https://https://forge.lthn.ai/core/scoop-bucket.git`)
|
||||
mustNoError(t, err)
|
||||
mustContains(t, out, `scoop bucket add host-uk $ScoopBucket`)
|
||||
mustNotContains(t, out, `https://https://forge.lthn.ai/core/scoop-bucket.git`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,29 +4,27 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRunRepoSetup_CreatesCoreConfigs(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example.com/test\n"), 0o644))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module example.com/test\n"), 0o644))
|
||||
|
||||
require.NoError(t, runRepoSetup(dir, false))
|
||||
mustNoError(t, runRepoSetup(dir, false))
|
||||
|
||||
for _, name := range []string{"build.yaml", "release.yaml", "test.yaml"} {
|
||||
path := filepath.Join(dir, ".core", name)
|
||||
_, err := os.Stat(path)
|
||||
require.NoErrorf(t, err, "expected %s to exist", path)
|
||||
mustNoErrorf(t, err, "expected %s to exist", path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetectProjectType_PrefersPackageOverComposer(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, "package.json"), []byte("{}\n"), 0o644))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(dir, "composer.json"), []byte("{}\n"), 0o644))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(dir, "package.json"), []byte("{}\n"), 0o644))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(dir, "composer.json"), []byte("{}\n"), 0o644))
|
||||
|
||||
require.Equal(t, "node", detectProjectType(dir))
|
||||
mustEqual(t, "node", detectProjectType(dir))
|
||||
}
|
||||
|
||||
func TestParseGitHubRepoURL_Good(t *testing.T) {
|
||||
|
|
@ -46,7 +44,7 @@ func TestParseGitHubRepoURL_Good(t *testing.T) {
|
|||
|
||||
for remote, expected := range cases {
|
||||
t.Run(remote, func(t *testing.T) {
|
||||
require.Equal(t, expected, parseGitHubRepoURL(remote))
|
||||
mustEqual(t, expected, parseGitHubRepoURL(remote))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package setup
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"dappco.re/go/core/scm/repos"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestFilterReposByTypes_Good(t *testing.T) {
|
||||
|
|
@ -16,9 +16,9 @@ func TestFilterReposByTypes_Good(t *testing.T) {
|
|||
|
||||
filtered := filterReposByTypes(reposList, []string{"module", "product"})
|
||||
|
||||
require.Len(t, filtered, 2)
|
||||
require.Equal(t, "module-a", filtered[0].Name)
|
||||
require.Equal(t, "product-a", filtered[1].Name)
|
||||
mustLen(t, filtered, 2)
|
||||
mustEqual(t, "module-a", filtered[0].Name)
|
||||
mustEqual(t, "product-a", filtered[1].Name)
|
||||
}
|
||||
|
||||
func TestFilterReposByTypes_EmptyFilter_Good(t *testing.T) {
|
||||
|
|
@ -29,6 +29,8 @@ func TestFilterReposByTypes_EmptyFilter_Good(t *testing.T) {
|
|||
|
||||
filtered := filterReposByTypes(reposList, nil)
|
||||
|
||||
require.Len(t, filtered, 2)
|
||||
require.Equal(t, reposList, filtered)
|
||||
mustLen(t, filtered, 2)
|
||||
if !reflect.DeepEqual(reposList, filtered) {
|
||||
t.Fatalf("want %v, got %v", reposList, filtered)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseCoverProfile_Good(t *testing.T) {
|
||||
|
|
@ -15,29 +13,29 @@ github.com/acme/project/foo/foo.go:1.1,3.1 2 1
|
|||
github.com/acme/project/foo/bar.go:1.1,4.1 3 0
|
||||
github.com/acme/project/baz/baz.go:1.1,2.1 4 4
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, snapshot.Packages, 2)
|
||||
require.Equal(t, "github.com/acme/project/baz", snapshot.Packages[0].Name)
|
||||
require.Equal(t, "github.com/acme/project/foo", snapshot.Packages[1].Name)
|
||||
require.InDelta(t, 100.0, snapshot.Packages[0].Coverage, 0.0001)
|
||||
require.InDelta(t, 40.0, snapshot.Packages[1].Coverage, 0.0001)
|
||||
require.InDelta(t, 66.6667, snapshot.Total.Coverage, 0.0001)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, snapshot.Packages, 2)
|
||||
mustEqual(t, "github.com/acme/project/baz", snapshot.Packages[0].Name)
|
||||
mustEqual(t, "github.com/acme/project/foo", snapshot.Packages[1].Name)
|
||||
mustInDelta(t, 100.0, snapshot.Packages[0].Coverage, 0.0001)
|
||||
mustInDelta(t, 40.0, snapshot.Packages[1].Coverage, 0.0001)
|
||||
mustInDelta(t, 66.6667, snapshot.Total.Coverage, 0.0001)
|
||||
}
|
||||
|
||||
func TestParseCoverProfile_Bad(t *testing.T) {
|
||||
_, err := ParseCoverProfile("mode: set\nbroken line")
|
||||
require.Error(t, err)
|
||||
mustError(t, err)
|
||||
}
|
||||
|
||||
func TestParseCoverOutput_Good(t *testing.T) {
|
||||
snapshot, err := ParseCoverOutput(`ok github.com/acme/project/foo 0.123s coverage: 75.0% of statements
|
||||
ok github.com/acme/project/bar 0.456s coverage: 50.0% of statements
|
||||
`)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, snapshot.Packages, 2)
|
||||
require.Equal(t, "github.com/acme/project/bar", snapshot.Packages[0].Name)
|
||||
require.Equal(t, "github.com/acme/project/foo", snapshot.Packages[1].Name)
|
||||
require.InDelta(t, 62.5, snapshot.Total.Coverage, 0.0001)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, snapshot.Packages, 2)
|
||||
mustEqual(t, "github.com/acme/project/bar", snapshot.Packages[0].Name)
|
||||
mustEqual(t, "github.com/acme/project/foo", snapshot.Packages[1].Name)
|
||||
mustInDelta(t, 62.5, snapshot.Total.Coverage, 0.0001)
|
||||
}
|
||||
|
||||
func TestCompareCoverage_Good(t *testing.T) {
|
||||
|
|
@ -58,14 +56,14 @@ func TestCompareCoverage_Good(t *testing.T) {
|
|||
}
|
||||
|
||||
comparison := CompareCoverage(previous, current)
|
||||
require.Len(t, comparison.Regressions, 1)
|
||||
require.Len(t, comparison.Improvements, 1)
|
||||
require.Len(t, comparison.NewPackages, 1)
|
||||
require.Empty(t, comparison.Removed)
|
||||
require.Equal(t, "pkg/a", comparison.Regressions[0].Name)
|
||||
require.Equal(t, "pkg/b", comparison.Improvements[0].Name)
|
||||
require.Equal(t, "pkg/c", comparison.NewPackages[0].Name)
|
||||
require.InDelta(t, 4.0, comparison.TotalDelta, 0.0001)
|
||||
mustLen(t, comparison.Regressions, 1)
|
||||
mustLen(t, comparison.Improvements, 1)
|
||||
mustLen(t, comparison.NewPackages, 1)
|
||||
mustEmpty(t, comparison.Removed)
|
||||
mustEqual(t, "pkg/a", comparison.Regressions[0].Name)
|
||||
mustEqual(t, "pkg/b", comparison.Improvements[0].Name)
|
||||
mustEqual(t, "pkg/c", comparison.NewPackages[0].Name)
|
||||
mustInDelta(t, 4.0, comparison.TotalDelta, 0.0001)
|
||||
}
|
||||
|
||||
func TestCoverageStore_Good(t *testing.T) {
|
||||
|
|
@ -83,26 +81,26 @@ func TestCoverageStore_Good(t *testing.T) {
|
|||
Total: CoveragePackage{Name: "total", Coverage: 82.5},
|
||||
}
|
||||
|
||||
require.NoError(t, store.Append(first))
|
||||
require.NoError(t, store.Append(second))
|
||||
mustNoError(t, store.Append(first))
|
||||
mustNoError(t, store.Append(second))
|
||||
|
||||
snapshots, err := store.Load()
|
||||
require.NoError(t, err)
|
||||
require.Len(t, snapshots, 2)
|
||||
require.Equal(t, first.CapturedAt, snapshots[0].CapturedAt)
|
||||
require.Equal(t, second.CapturedAt, snapshots[1].CapturedAt)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, snapshots, 2)
|
||||
mustEqual(t, first.CapturedAt, snapshots[0].CapturedAt)
|
||||
mustEqual(t, second.CapturedAt, snapshots[1].CapturedAt)
|
||||
|
||||
latest, err := store.Latest()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, second.CapturedAt, latest.CapturedAt)
|
||||
mustNoError(t, err)
|
||||
mustEqual(t, second.CapturedAt, latest.CapturedAt)
|
||||
}
|
||||
|
||||
func TestCoverageStore_Bad(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "coverage.json")
|
||||
require.NoError(t, os.WriteFile(path, []byte("{"), 0o600))
|
||||
mustNoError(t, os.WriteFile(path, []byte("{"), 0o600))
|
||||
|
||||
store := NewCoverageStore(path)
|
||||
_, err := store.Load()
|
||||
require.Error(t, err)
|
||||
mustError(t, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package devkit
|
|||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestScanSecrets_Good(t *testing.T) {
|
||||
|
|
@ -14,7 +12,7 @@ func TestScanSecrets_Good(t *testing.T) {
|
|||
})
|
||||
|
||||
scanSecretsRunner = func(dir string) ([]byte, error) {
|
||||
require.Equal(t, "/tmp/project", dir)
|
||||
mustEqual(t, "/tmp/project", dir)
|
||||
return []byte(`RuleID,File,StartLine,StartColumn,Description,Match
|
||||
github-token,config.yml,12,4,GitHub token detected,ghp_exampletoken1234567890
|
||||
aws-access-key-id,creds.txt,7,1,AWS access key detected,AKIA1234567890ABCDEF
|
||||
|
|
@ -22,20 +20,20 @@ aws-access-key-id,creds.txt,7,1,AWS access key detected,AKIA1234567890ABCDEF
|
|||
}
|
||||
|
||||
findings, err := ScanSecrets("/tmp/project")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, findings, 2)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, findings, 2)
|
||||
|
||||
require.Equal(t, "github-token", findings[0].Rule)
|
||||
require.Equal(t, "config.yml", findings[0].Path)
|
||||
require.Equal(t, 12, findings[0].Line)
|
||||
require.Equal(t, 4, findings[0].Column)
|
||||
require.Equal(t, "ghp_exampletoken1234567890", findings[0].Snippet)
|
||||
mustEqual(t, "github-token", findings[0].Rule)
|
||||
mustEqual(t, "config.yml", findings[0].Path)
|
||||
mustEqual(t, 12, findings[0].Line)
|
||||
mustEqual(t, 4, findings[0].Column)
|
||||
mustEqual(t, "ghp_exampletoken1234567890", findings[0].Snippet)
|
||||
|
||||
require.Equal(t, "aws-access-key-id", findings[1].Rule)
|
||||
require.Equal(t, "creds.txt", findings[1].Path)
|
||||
require.Equal(t, 7, findings[1].Line)
|
||||
require.Equal(t, 1, findings[1].Column)
|
||||
require.Equal(t, "AKIA1234567890ABCDEF", findings[1].Snippet)
|
||||
mustEqual(t, "aws-access-key-id", findings[1].Rule)
|
||||
mustEqual(t, "creds.txt", findings[1].Path)
|
||||
mustEqual(t, 7, findings[1].Line)
|
||||
mustEqual(t, 1, findings[1].Column)
|
||||
mustEqual(t, "AKIA1234567890ABCDEF", findings[1].Snippet)
|
||||
}
|
||||
|
||||
func TestScanSecrets_ReportsFindingsOnExitError(t *testing.T) {
|
||||
|
|
@ -51,14 +49,14 @@ token,test.txt,3,2,Token detected,secret-value
|
|||
}
|
||||
|
||||
findings, err := ScanSecrets("/tmp/project")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, findings, 1)
|
||||
require.Equal(t, "token", findings[0].Rule)
|
||||
require.Equal(t, 3, findings[0].Line)
|
||||
require.Equal(t, 2, findings[0].Column)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, findings, 1)
|
||||
mustEqual(t, "token", findings[0].Rule)
|
||||
mustEqual(t, 3, findings[0].Line)
|
||||
mustEqual(t, 2, findings[0].Column)
|
||||
}
|
||||
|
||||
func TestParseGitleaksCSV_Bad(t *testing.T) {
|
||||
_, err := parseGitleaksCSV([]byte("rule_id,file,start_line\nunterminated,\"broken"))
|
||||
require.Error(t, err)
|
||||
mustError(t, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,54 +4,52 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestScanDir_Good(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
|
||||
require.NoError(t, os.WriteFile(filepath.Join(root, "config.yml"), []byte(`
|
||||
mustNoError(t, os.WriteFile(filepath.Join(root, "config.yml"), []byte(`
|
||||
api_key: "ghp_abcdefghijklmnopqrstuvwxyz1234"
|
||||
`), 0o600))
|
||||
|
||||
require.NoError(t, os.Mkdir(filepath.Join(root, "nested"), 0o755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(root, "nested", "creds.txt"), []byte("access_key = AKIA1234567890ABCDEF\n"), 0o600))
|
||||
mustNoError(t, os.Mkdir(filepath.Join(root, "nested"), 0o755))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(root, "nested", "creds.txt"), []byte("access_key = AKIA1234567890ABCDEF\n"), 0o600))
|
||||
|
||||
findings, err := ScanDir(root)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, findings, 2)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, findings, 2)
|
||||
|
||||
require.Equal(t, "github-token", findings[0].Rule)
|
||||
require.Equal(t, 2, findings[0].Line)
|
||||
require.Equal(t, "config.yml", filepath.Base(findings[0].Path))
|
||||
mustEqual(t, "github-token", findings[0].Rule)
|
||||
mustEqual(t, 2, findings[0].Line)
|
||||
mustEqual(t, "config.yml", filepath.Base(findings[0].Path))
|
||||
|
||||
require.Equal(t, "aws-access-key-id", findings[1].Rule)
|
||||
require.Equal(t, 1, findings[1].Line)
|
||||
require.Equal(t, "creds.txt", filepath.Base(findings[1].Path))
|
||||
mustEqual(t, "aws-access-key-id", findings[1].Rule)
|
||||
mustEqual(t, 1, findings[1].Line)
|
||||
mustEqual(t, "creds.txt", filepath.Base(findings[1].Path))
|
||||
}
|
||||
|
||||
func TestScanDir_SkipsBinaryAndIgnoredDirs(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
|
||||
require.NoError(t, os.Mkdir(filepath.Join(root, ".git"), 0o755))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(root, ".git", "config"), []byte("token=ghp_abcdefghijklmnopqrstuvwxyz1234"), 0o600))
|
||||
require.NoError(t, os.WriteFile(filepath.Join(root, "blob.bin"), []byte{0, 1, 2, 3, 4}, 0o600))
|
||||
mustNoError(t, os.Mkdir(filepath.Join(root, ".git"), 0o755))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(root, ".git", "config"), []byte("token=ghp_abcdefghijklmnopqrstuvwxyz1234"), 0o600))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(root, "blob.bin"), []byte{0, 1, 2, 3, 4}, 0o600))
|
||||
|
||||
findings, err := ScanDir(root)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, findings)
|
||||
mustNoError(t, err)
|
||||
mustEmpty(t, findings)
|
||||
}
|
||||
|
||||
func TestScanDir_ReportsGenericAssignments(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
|
||||
require.NoError(t, os.WriteFile(filepath.Join(root, "secrets.env"), []byte("client_secret: abcdefghijklmnop\n"), 0o600))
|
||||
mustNoError(t, os.WriteFile(filepath.Join(root, "secrets.env"), []byte("client_secret: abcdefghijklmnop\n"), 0o600))
|
||||
|
||||
findings, err := ScanDir(root)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, findings, 1)
|
||||
require.Equal(t, "generic-secret-assignment", findings[0].Rule)
|
||||
require.Equal(t, 1, findings[0].Line)
|
||||
require.Equal(t, 1, findings[0].Column)
|
||||
mustNoError(t, err)
|
||||
mustLen(t, findings, 1)
|
||||
mustEqual(t, "generic-secret-assignment", findings[0].Rule)
|
||||
mustEqual(t, 1, findings[0].Line)
|
||||
mustEqual(t, 1, findings[0].Column)
|
||||
}
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -13,7 +13,6 @@ require (
|
|||
dappco.re/go/core/log v0.1.2
|
||||
dappco.re/go/core/scm v0.6.1
|
||||
github.com/kluctl/go-embed-python v0.0.0-3.13.1-20241219-1
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/term v0.41.0
|
||||
golang.org/x/text v0.35.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
|
@ -33,7 +32,6 @@ require (
|
|||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
|
|
@ -51,7 +49,6 @@ require (
|
|||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import (
|
|||
"time"
|
||||
|
||||
"dappco.re/go/core/scm/manifest"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var fixedTime = time.Date(2026, 3, 9, 15, 0, 0, 0, time.UTC)
|
||||
|
|
@ -30,26 +28,28 @@ func TestGenerate_Good(t *testing.T) {
|
|||
}
|
||||
|
||||
data, err := GenerateAt(m, "abc123def456", "v1.0.0", fixedTime)
|
||||
require.NoError(t, err)
|
||||
mustNoError(t, err)
|
||||
|
||||
var snap Snapshot
|
||||
require.NoError(t, json.Unmarshal(data, &snap))
|
||||
mustNoError(t, json.Unmarshal(data, &snap))
|
||||
|
||||
assert.Equal(t, 1, snap.Schema)
|
||||
assert.Equal(t, "test-app", snap.Code)
|
||||
assert.Equal(t, "Test App", snap.Name)
|
||||
assert.Equal(t, "1.0.0", snap.Version)
|
||||
assert.Equal(t, "A test application", snap.Description)
|
||||
assert.Equal(t, "abc123def456", snap.Commit)
|
||||
assert.Equal(t, "v1.0.0", snap.Tag)
|
||||
assert.Equal(t, "2026-03-09T15:00:00Z", snap.Built)
|
||||
assert.Equal(t, "HLCRF", snap.Layout)
|
||||
assert.Equal(t, "main-content", snap.Slots["C"])
|
||||
assert.Len(t, snap.Daemons, 1)
|
||||
assert.Equal(t, "core-php", snap.Daemons["serve"].Binary)
|
||||
require.NotNil(t, snap.Permissions)
|
||||
assert.Equal(t, []string{"./photos/"}, snap.Permissions.Read)
|
||||
assert.Equal(t, []string{"core/media"}, snap.Modules)
|
||||
mustEqual(t, 1, snap.Schema)
|
||||
mustEqual(t, "test-app", snap.Code)
|
||||
mustEqual(t, "Test App", snap.Name)
|
||||
mustEqual(t, "1.0.0", snap.Version)
|
||||
mustEqual(t, "A test application", snap.Description)
|
||||
mustEqual(t, "abc123def456", snap.Commit)
|
||||
mustEqual(t, "v1.0.0", snap.Tag)
|
||||
mustEqual(t, "2026-03-09T15:00:00Z", snap.Built)
|
||||
mustEqual(t, "HLCRF", snap.Layout)
|
||||
mustEqual(t, "main-content", snap.Slots["C"])
|
||||
mustLenMap(t, snap.Daemons, 1)
|
||||
mustEqual(t, "core-php", snap.Daemons["serve"].Binary)
|
||||
if snap.Permissions == nil {
|
||||
t.Fatal("expected non-nil permissions")
|
||||
}
|
||||
mustDeepEqual(t, []string{"./photos/"}, snap.Permissions.Read)
|
||||
mustDeepEqual(t, []string{"core/media"}, snap.Modules)
|
||||
}
|
||||
|
||||
func TestGenerate_Good_NoDaemons(t *testing.T) {
|
||||
|
|
@ -60,19 +60,22 @@ func TestGenerate_Good_NoDaemons(t *testing.T) {
|
|||
}
|
||||
|
||||
data, err := GenerateAt(m, "abc123", "v0.1.0", fixedTime)
|
||||
require.NoError(t, err)
|
||||
mustNoError(t, err)
|
||||
|
||||
var snap Snapshot
|
||||
require.NoError(t, json.Unmarshal(data, &snap))
|
||||
mustNoError(t, json.Unmarshal(data, &snap))
|
||||
|
||||
assert.Equal(t, 1, snap.Schema)
|
||||
assert.Equal(t, "simple", snap.Code)
|
||||
assert.Nil(t, snap.Daemons)
|
||||
assert.Nil(t, snap.Permissions)
|
||||
mustEqual(t, 1, snap.Schema)
|
||||
mustEqual(t, "simple", snap.Code)
|
||||
if snap.Daemons != nil {
|
||||
t.Fatalf("expected nil daemons, got %v", snap.Daemons)
|
||||
}
|
||||
if snap.Permissions != nil {
|
||||
t.Fatalf("expected nil permissions, got %v", snap.Permissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate_Bad_NilManifest(t *testing.T) {
|
||||
_, err := Generate(nil, "abc123", "v1.0.0")
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "manifest is nil")
|
||||
mustErrorContains(t, err, "manifest is nil")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue