Skip to content

Commit 43a33ef

Browse files
committed
refactor: validator
1 parent 5b5f980 commit 43a33ef

File tree

4 files changed

+108
-11
lines changed

4 files changed

+108
-11
lines changed

internal/callgraph/graph.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import (
77
"sort"
88
)
99

10+
// MakeEdgeString returns a string that represents an edge in the call graph.
1011
func MakeEdgeString(src, dst string) string {
1112
return fmt.Sprintf("⟦%s:KoDeDgE:%s→%s⟧", checksumEdge(src, dst), src, dst)
1213
}
1314

15+
// ParseEdges returns a list of edges from the given data.
1416
func ParseEdges(data []byte) [][2]string {
1517
var result [][2]string
1618
re := regexp.MustCompile(`⟦([0-9a-fA-F]+):KoDeDgE:([a-zA-Z0-9\-.~_/]*?)→([a-zA-Z0-9\-.~_/]*?)⟧`)
@@ -33,8 +35,9 @@ func ParseEdges(data []byte) [][2]string {
3335
return result
3436
}
3537

38+
// checksumEdge returns a checksum for the given edge.
3639
func checksumEdge(src, dst string) string {
3740
edge := fmt.Sprintf("KoDeDgE:%s→%s", src, dst)
38-
sum := sha256.Sum256([]byte(edge))
39-
return fmt.Sprintf("%0x", sum)[:8]
41+
sum := fmt.Sprintf("%0x", sha256.Sum256([]byte(edge)))[:8]
42+
return sum
4043
}

kod.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ func newKod(opts options) (*Kod, error) {
297297
return nil, err
298298
}
299299

300-
if err := registry.ValidateRegistrations(kod.regs); err != nil {
300+
if err := validateRegistrations(kod.regs); err != nil {
301301
return nil, err
302302
}
303303

304-
if err := registry.CheckCircularDependency(kod.regs); err != nil {
304+
if err := checkCircularDependency(kod.regs); err != nil {
305305
return nil, err
306306
}
307307

internal/registry/validate.go validate.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package registry
1+
package kod
22

33
import (
44
"errors"
@@ -10,9 +10,9 @@ import (
1010
"github.com/go-kod/kod/internal/reflects"
1111
)
1212

13-
// CheckCircularDependency checks that there are no circular dependencies
13+
// checkCircularDependency checks that there are no circular dependencies
1414
// between registered components.
15-
func CheckCircularDependency(reg []*Registration) error {
15+
func checkCircularDependency(reg []*Registration) error {
1616
g := graph.New(graph.StringHash, graph.Directed(), graph.PreventCycles())
1717

1818
for _, reg := range reg {
@@ -39,19 +39,19 @@ func CheckCircularDependency(reg []*Registration) error {
3939
return errors.Join(errs...)
4040
}
4141

42-
// ValidateRegistrations checks that all registered component interfaces are
42+
// validateRegistrations checks that all registered component interfaces are
4343
// implemented by a registered component implementation struct.
44-
func ValidateRegistrations(reg []*Registration) error {
44+
func validateRegistrations(regs []*Registration) error {
4545
// Gather the set of registered interfaces.
4646
intfs := map[reflect.Type]struct{}{}
47-
for _, reg := range reg {
47+
for _, reg := range regs {
4848
intfs[reg.Iface] = struct{}{}
4949
}
5050

5151
// Check that for every kod.Ref[T] field in a component implementation
5252
// struct, T is a registered interface.
5353
var errs []error
54-
for _, reg := range reg {
54+
for _, reg := range regs {
5555
for i := 0; i < reg.Impl.NumField(); i++ {
5656
f := reg.Impl.Field(i)
5757
switch {

validate_test.go

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package kod
2+
3+
import (
4+
"io"
5+
"reflect"
6+
"strings"
7+
"testing"
8+
9+
"github.com/go-kod/kod/internal/reflects"
10+
"github.com/go-kod/kod/internal/registry"
11+
)
12+
13+
func TestValidateUnregisteredRef(t *testing.T) {
14+
type foo interface{}
15+
type fooImpl struct{ Ref[io.Reader] }
16+
regs := []*registry.Registration{
17+
{
18+
Name: "foo",
19+
Iface: reflects.TypeFor[foo](),
20+
Impl: reflects.TypeFor[fooImpl](),
21+
},
22+
}
23+
err := validateRegistrations(regs)
24+
if err == nil {
25+
t.Fatal("unexpected validateRegistrations success")
26+
}
27+
const want = "component io.Reader was not registered"
28+
if !strings.Contains(err.Error(), want) {
29+
t.Fatalf("validateRegistrations: got %q, want %q", err, want)
30+
}
31+
}
32+
33+
// TestValidateNoRegistrations tests that validateRegistrations succeeds on an
34+
// empty set of registrations.
35+
func TestValidateNoRegistrations(t *testing.T) {
36+
if err := validateRegistrations(nil); err != nil {
37+
t.Fatal(err)
38+
}
39+
}
40+
41+
func TestMultipleRegistrations(t *testing.T) {
42+
type foo interface{}
43+
type fooImpl struct{ Ref[io.Reader] }
44+
regs := []*Registration{
45+
{
46+
Name: "github.com/go-kod/kod/Main",
47+
Iface: reflect.TypeOf((*Main)(nil)).Elem(),
48+
Impl: reflect.TypeOf(fooImpl{}),
49+
Refs: `⟦48699770:KoDeDgE:github.com/go-kod/kod/Main→github.com/go-kod/kod/tests/graphcase/test1Controller⟧`,
50+
},
51+
{
52+
Name: "github.com/go-kod/kod/Main",
53+
Iface: reflect.TypeOf((*foo)(nil)).Elem(),
54+
Impl: reflect.TypeOf(fooImpl{}),
55+
Refs: `⟦48699770:KoDeDgE:github.com/go-kod/kod/tests/graphcase/test1Controller→github.com/go-kod/kod/Main⟧`,
56+
},
57+
}
58+
err := checkCircularDependency(regs)
59+
if err == nil {
60+
t.Fatal("unexpected checkCircularDependency success")
61+
}
62+
const want = "components [github.com/go-kod/kod/Main], error vertex already exists"
63+
if !strings.Contains(err.Error(), want) {
64+
t.Fatalf("checkCircularDependency: got %q, want %q", err, want)
65+
}
66+
}
67+
68+
func TestCycleRegistrations(t *testing.T) {
69+
type test1Controller interface{}
70+
type test1ControllerImpl struct{ Ref[io.Reader] }
71+
type mainImpl struct{ Ref[test1Controller] }
72+
regs := []*Registration{
73+
{
74+
Name: "github.com/go-kod/kod/Main",
75+
Iface: reflect.TypeOf((*Main)(nil)).Elem(),
76+
Impl: reflect.TypeOf(mainImpl{}),
77+
Refs: `⟦48699770:KoDeDgE:github.com/go-kod/kod/Main→github.com/go-kod/kod/test1Controller⟧`,
78+
},
79+
{
80+
Name: "github.com/go-kod/kod/test1Controller",
81+
Iface: reflect.TypeOf((*test1Controller)(nil)).Elem(),
82+
Impl: reflect.TypeOf(test1ControllerImpl{}),
83+
Refs: `⟦b8422d0e:KoDeDgE:github.com/go-kod/kod/test1Controller→github.com/go-kod/kod/Main⟧`,
84+
},
85+
}
86+
err := checkCircularDependency(regs)
87+
if err == nil {
88+
t.Fatal("unexpected checkCircularDependency success")
89+
}
90+
const want = "components [github.com/go-kod/kod/test1Controller] and [github.com/go-kod/kod/Main] have cycle Ref"
91+
if !strings.Contains(err.Error(), want) {
92+
t.Fatalf("checkCircularDependency: got %q, want %q", err, want)
93+
}
94+
}

0 commit comments

Comments
 (0)