fleet/server/archtest/archtest_test.go
Victor Lyuboslavsky 4b007e20e1
Android scaffold (#26274)
Android scaffold code and refactorings
- Android packages intended to be decoupled from other Fleet code

Video explaining the PR: https://www.youtube.com/watch?v=cza-35Z9Wxk

# Checklist for submitter

- [x] If database migrations are included, checked table schema to
confirm autoupdate
- For database migrations:
- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).
- [x] Added/updated automated tests
- [x] Manual QA for all new/changed functionality
2025-02-13 14:32:19 -06:00

202 lines
5.3 KiB
Go

package archtest
import (
"fmt"
"strings"
"testing"
)
const packagePrefix = "github.com/fleetdm/fleet/v4/server/archtest/test_files/"
func TestPackage_ShouldNotDependOn(t *testing.T) {
t.Run("Succeeds on non dependencies", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage").
ShouldNotDependOn(packagePrefix + "nodependency")
assertNoError(t, mockT)
})
t.Run("Fails on dependencies", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage").
ShouldNotDependOn(packagePrefix + "dependency")
assertError(t, mockT,
packagePrefix+"testpackage",
packagePrefix+"dependency")
})
t.Run("Supports testing against packages in the go root", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage").
ShouldNotDependOn("crypto")
assertError(t, mockT,
packagePrefix+"testpackage",
"crypto")
})
t.Run("Fails on transative dependencies", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage").
ShouldNotDependOn(packagePrefix + "transative")
assertError(t, mockT,
packagePrefix+"testpackage",
packagePrefix+"dependency",
packagePrefix+"transative")
})
t.Run("Supports multiple packages at once", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"dontdependonanything",
packagePrefix+"testpackage").
ShouldNotDependOn(packagePrefix+"nodependency",
packagePrefix+"dependency")
assertError(t, mockT,
packagePrefix+"testpackage",
packagePrefix+"dependency")
})
t.Run("Supports wildcard matching", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"...").
ShouldNotDependOn(packagePrefix + "nodependency")
assertNoError(t, mockT)
NewPackageTest(mockT, packagePrefix+"testpackage/nested/...").
ShouldNotDependOn(packagePrefix + "...")
assertError(t, mockT, packagePrefix+"testpackage/nested/dep",
packagePrefix+"nesteddependency")
})
t.Run("Supports checking imports in test files", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage/...").
ShouldNotDependOn(packagePrefix + "testfiledeps/testonlydependency")
assertNoError(t, mockT)
NewPackageTest(mockT, packagePrefix+"testpackage/...").
WithTests().
ShouldNotDependOn(packagePrefix + "testfiledeps/testonlydependency")
assertError(t, mockT,
packagePrefix+"testpackage/nested/dep",
packagePrefix+"testfiledeps/testonlydependency",
)
})
t.Run("Supports checking imports from test packages", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage/...").
ShouldNotDependOn(packagePrefix + "testfiledeps/testpkgdependency")
assertNoError(t, mockT)
NewPackageTest(mockT, packagePrefix+"testpackage/...").
WithTests().
ShouldNotDependOn(packagePrefix + "testfiledeps/testpkgdependency")
assertError(t, mockT,
packagePrefix+"testpackage/nested/dep_test",
packagePrefix+"testfiledeps/testpkgdependency",
)
})
t.Run("Supports Ignoring packages", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage/nested/dep").
IgnorePackages(packagePrefix + "testpackage/nested/dep").
ShouldNotDependOn(packagePrefix + "nesteddependency")
assertNoError(t, mockT)
})
t.Run("Ignored packages ignore ignored transitive packages", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"testpackage").
IgnorePackages("github.com/this/is/verifying/multiple/exclusions", packagePrefix+"...").
IgnorePackages("github.com/this/is/verifying/chaining").
ShouldNotDependOn(packagePrefix + "transative")
assertNoError(t, mockT)
})
t.Run("Fails on packages that do not exist", func(t *testing.T) {
mockT := new(testingT)
NewPackageTest(mockT, packagePrefix+"dontexist/sorry").
ShouldNotDependOn(packagePrefix + "dependency")
assertError(t, mockT)
mockT = new(testingT)
NewPackageTest(mockT, "DONT__WORK").
ShouldNotDependOn(packagePrefix + "dependency")
assertError(t, mockT)
mockT = new(testingT)
NewPackageTest(mockT, packagePrefix+"dontexist/...").
ShouldNotDependOn(packagePrefix + "dependency")
assertError(t, mockT)
})
}
func assertNoError(t *testing.T, mockT *testingT) {
t.Helper()
if mockT.errored() {
t.Fatalf("archtest should not have failed but, %+v", mockT.message())
}
}
func assertError(t *testing.T, mockT *testingT, dependencyTrace ...string) {
t.Helper()
if !mockT.errored() {
t.Fatal("archtest did not fail on dependency")
}
if dependencyTrace == nil {
return
}
s := strings.Builder{}
s.WriteString("Error: package dependency not allowed. Dependency chain:\n")
for i, v := range dependencyTrace {
s.WriteString(strings.Repeat("\t", i))
s.WriteString(v + "\n")
}
if mockT.message() != s.String() {
t.Errorf("expected %s got error message: %s", s.String(), mockT.message())
}
}
type testingT struct {
errors [][]interface{}
}
func (t *testingT) Errorf(format string, args ...any) {
t.errors = append(t.errors, append([]interface{}{format}, args...))
}
func (t testingT) errored() bool {
return len(t.errors) != 0
}
func (t *testingT) message() string {
if len(t.errors[0]) == 1 {
return t.errors[0][0].(string)
}
return fmt.Sprintf(t.errors[0][0].(string), t.errors[0][1:]...)
}