tinyrelayfile
tinyrelay/protocol/dependencies_test.go/

protocol/dependencies_test.go raw
1package protocol_test
2
3import (
4 "go/ast"
5 "go/parser"
6 "go/token"
7 "os/exec"
8 "path/filepath"
9 "runtime"
10 "slices"
11 "strings"
12 "testing"
13)
14
15func TestPublicProtocolDependencyGraph(t *testing.T) {
16 for _, name := range []string{"nostr", "auth"} {
17 t.Run(name, func(t *testing.T) {
18 cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), "list", "-deps", "-f", "{{.ImportPath}}", "./"+name)
19 out, err := cmd.CombinedOutput()
20 if err != nil {
21 t.Fatalf("dependency graph: %v\n%s", err, out)
22 }
23 found := false
24 for _, dependency := range strings.Fields(string(out)) {
25 if dependency == modulePath+"/protocol/"+name {
26 found = true
27 }
28 if strings.HasPrefix(dependency, modulePath+"/") && dependency != modulePath+"/protocol/nostr" && dependency != modulePath+"/protocol/auth" {
29 t.Errorf("protocol/%s depends on host package %s", name, dependency)
30 }
31 for _, forbidden := range []string{"modernc.org/sqlite", "github.com/prometheus/", "go.opentelemetry.io/"} {
32 if strings.HasPrefix(dependency, forbidden) {
33 t.Errorf("protocol/%s depends on host infrastructure %s", name, dependency)
34 }
35 }
36 }
37 if !found {
38 t.Fatal("dependency graph omitted target package")
39 }
40 })
41 }
42}
43
44// Keep this generic package's public surface deliberate: feature-specific
45// kind constants, private-kind classification and room/job semantics belong
46// to their owning packages, not the Nostr wire model.
47func TestNostrPublicSurface(t *testing.T) {
48 want := strings.Fields("Event Filter Validate Parse Canonical Tag TagValues Expiration Difficulty CommittedDifficulty Sign GenerateKey PublicKey IsEphemeral IsReplaceable IsAddressable ParseFilter Matches SearchTerms Filter.MarshalJSON")
49 var got []string
50 files, err := filepath.Glob("nostr/*.go")
51 if err != nil {
52 t.Fatal(err)
53 }
54 for _, path := range files {
55 if strings.HasSuffix(path, "_test.go") {
56 continue
57 }
58 file, err := parser.ParseFile(token.NewFileSet(), path, nil, 0)
59 if err != nil {
60 t.Fatal(err)
61 }
62 for _, decl := range file.Decls {
63 switch decl := decl.(type) {
64 case *ast.FuncDecl:
65 if !decl.Name.IsExported() {
66 continue
67 }
68 name := decl.Name.Name
69 if decl.Recv != nil {
70 receiver := decl.Recv.List[0].Type
71 if pointer, ok := receiver.(*ast.StarExpr); ok {
72 receiver = pointer.X
73 }
74 name = receiver.(*ast.Ident).Name + "." + name
75 }
76 got = append(got, name)
77 case *ast.GenDecl:
78 for _, spec := range decl.Specs {
79 switch spec := spec.(type) {
80 case *ast.TypeSpec:
81 if spec.Name.IsExported() {
82 got = append(got, spec.Name.Name)
83 }
84 case *ast.ValueSpec:
85 for _, name := range spec.Names {
86 if name.IsExported() {
87 got = append(got, name.Name)
88 }
89 }
90 }
91 }
92 }
93 }
94 }
95 slices.Sort(got)
96 slices.Sort(want)
97 if !slices.Equal(got, want) {
98 t.Fatalf("Nostr public API changed; review protocol scope\ngot: %v\nwant: %v", got, want)
99 }
100}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs