feat: add phone frequency controls and modularize codebase
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type declaration struct {
|
||||
Name string `json:"name"`
|
||||
Kind string `json:"kind"`
|
||||
Receiver string `json:"receiver,omitempty"`
|
||||
File string `json:"file"`
|
||||
SHA256 string `json:"sha256"`
|
||||
}
|
||||
|
||||
type manifest struct {
|
||||
Version string `json:"version"`
|
||||
Source string `json:"source"`
|
||||
Declarations []declaration `json:"declarations"`
|
||||
}
|
||||
|
||||
var requiredFiles = []string{
|
||||
"manager.go",
|
||||
"pool.go",
|
||||
"connection.go",
|
||||
"reconnect.go",
|
||||
"flow_control.go",
|
||||
"submit.go",
|
||||
"deliver.go",
|
||||
"protocol_log.go",
|
||||
"transport.go",
|
||||
}
|
||||
|
||||
var requiredTests = []string{
|
||||
"TestConnectionPoolAcquiresAcrossConnections",
|
||||
"TestManagerDisconnectChannelRemovesPoolAndStopsReconnects",
|
||||
"TestNormalizeUpstreamConfigDefaults",
|
||||
"TestFailedSupplierConnectionReconnectsWhenEndpointRecovers",
|
||||
"TestHandleConnectionLossNotifiesPendingSubmitters",
|
||||
"TestHeartbeatTimeoutClosesConnectionAndSchedulesReconnect",
|
||||
"TestReconnectDelayUsesCappedBackoffAndSlowAuthenticationRetry",
|
||||
"TestHeartbeatResponseClearsOnlyMatchingRequest",
|
||||
"TestSplitSubmitContentUCS2LongMessage",
|
||||
"TestAssembleLongUplinkOutOfOrder",
|
||||
"TestSubmitRequestPacketUsesCMPP2PacketForCMPP20Channel",
|
||||
"TestSubmitRequestPacketUsesCMPP3PacketForCMPP30Channel",
|
||||
"TestHandleCMPP2DeliverReceiptPostsReceiptEvent",
|
||||
"TestReceiptStatusTreatsNonDeliveredFinalStatesAsUndelivered",
|
||||
"TestEmitProtocolLogPostsSafeOutboundPacketEvent",
|
||||
}
|
||||
|
||||
func main() {
|
||||
root, err := os.Getwd()
|
||||
must(err)
|
||||
payload, err := os.ReadFile(filepath.Join(root, "docs", "contracts", "upstream-r7-declarations.json"))
|
||||
must(err)
|
||||
var contract manifest
|
||||
must(json.Unmarshal(payload, &contract))
|
||||
if contract.Version != "R7" {
|
||||
fail("unexpected contract version %q", contract.Version)
|
||||
}
|
||||
|
||||
upstreamDir := filepath.Join(root, "gateway", "internal", "upstream")
|
||||
actual := map[string]declaration{}
|
||||
for _, name := range requiredFiles {
|
||||
path := filepath.Join(upstreamDir, name)
|
||||
source, err := os.ReadFile(path)
|
||||
must(err)
|
||||
if !bytes.HasPrefix(source, []byte("package upstream")) {
|
||||
fail("%s must remain in package upstream", name)
|
||||
}
|
||||
for _, item := range declarationsInFile(path, source) {
|
||||
key := declarationKey(item)
|
||||
if previous, exists := actual[key]; exists {
|
||||
fail("duplicate declaration %s in %s and %s", key, previous.File, item.File)
|
||||
}
|
||||
actual[key] = item
|
||||
}
|
||||
}
|
||||
for _, expected := range contract.Declarations {
|
||||
key := declarationKey(expected)
|
||||
item, ok := actual[key]
|
||||
if !ok {
|
||||
fail("missing declaration %s expected in %s", key, expected.File)
|
||||
}
|
||||
if item.File != expected.File {
|
||||
fail("%s moved to %s, expected %s", key, item.File, expected.File)
|
||||
}
|
||||
if item.SHA256 != expected.SHA256 {
|
||||
fail("%s implementation changed: %s != %s", key, item.SHA256, expected.SHA256)
|
||||
}
|
||||
}
|
||||
|
||||
managerSource, err := os.ReadFile(filepath.Join(upstreamDir, "manager.go"))
|
||||
must(err)
|
||||
if lines := bytes.Count(managerSource, []byte{'\n'}); lines > 250 {
|
||||
fail("stable manager.go grew to %d lines", lines)
|
||||
}
|
||||
for _, entry := range []string{
|
||||
"type Manager struct",
|
||||
"type ConnectionState struct",
|
||||
"func (m *Manager) ConnectChannel(",
|
||||
"func (m *Manager) DisconnectChannel(",
|
||||
} {
|
||||
assertContains(managerSource, entry)
|
||||
}
|
||||
submitSource, err := os.ReadFile(filepath.Join(upstreamDir, "submit.go"))
|
||||
must(err)
|
||||
assertContains(submitSource, "func (m *Manager) Submit(")
|
||||
|
||||
controlSource, err := os.ReadFile(filepath.Join(root, "gateway", "internal", "control", "server.go"))
|
||||
must(err)
|
||||
for _, entry := range []string{
|
||||
"*upstream.Manager",
|
||||
"s.Upstream.ConnectChannel",
|
||||
"s.Upstream.DisconnectChannel",
|
||||
"server.Upstream.Submit",
|
||||
} {
|
||||
assertContains(controlSource, entry)
|
||||
}
|
||||
mainSource, err := os.ReadFile(filepath.Join(root, "gateway", "cmd", "gateway", "main.go"))
|
||||
must(err)
|
||||
assertContains(mainSource, "&upstream.Manager{APIBaseURL: apiBaseURL}")
|
||||
|
||||
longMessageSource, err := os.ReadFile(filepath.Join(upstreamDir, "long_message.go"))
|
||||
must(err)
|
||||
for _, entry := range []string{
|
||||
"func splitSubmitContent(",
|
||||
"func assembleLongUplink(",
|
||||
"func pruneLongUplinkAssemblies(",
|
||||
} {
|
||||
assertContains(longMessageSource, entry)
|
||||
}
|
||||
|
||||
var tests bytes.Buffer
|
||||
testFiles, err := filepath.Glob(filepath.Join(upstreamDir, "*_test.go"))
|
||||
must(err)
|
||||
for _, path := range testFiles {
|
||||
source, err := os.ReadFile(path)
|
||||
must(err)
|
||||
tests.Write(source)
|
||||
}
|
||||
for _, test := range requiredTests {
|
||||
assertContains(tests.Bytes(), "func "+test+"(")
|
||||
}
|
||||
|
||||
fmt.Printf(
|
||||
"R7 upstream facade verified: %d declarations across %d focused files; stable entries and %d critical tests preserved.\n",
|
||||
len(contract.Declarations), len(requiredFiles), len(requiredTests),
|
||||
)
|
||||
}
|
||||
|
||||
func declarationsInFile(path string, source []byte) []declaration {
|
||||
fset := token.NewFileSet()
|
||||
file, err := parser.ParseFile(fset, path, source, parser.ParseComments)
|
||||
must(err)
|
||||
var result []declaration
|
||||
for _, decl := range file.Decls {
|
||||
if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.IMPORT {
|
||||
continue
|
||||
}
|
||||
name, kind, receiver := declarationIdentity(decl)
|
||||
start := declarationStart(decl)
|
||||
code := strings.TrimSpace(string(source[fset.Position(start).Offset:fset.Position(decl.End()).Offset]))
|
||||
hash := sha256.Sum256([]byte(strings.ReplaceAll(code, "\r\n", "\n")))
|
||||
result = append(result, declaration{
|
||||
Name: name, Kind: kind, Receiver: receiver, File: filepath.Base(path),
|
||||
SHA256: hex.EncodeToString(hash[:]),
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func declarationIdentity(decl ast.Decl) (name string, kind string, receiver string) {
|
||||
switch typed := decl.(type) {
|
||||
case *ast.FuncDecl:
|
||||
return typed.Name.Name, "func", receiverName(typed)
|
||||
case *ast.GenDecl:
|
||||
if len(typed.Specs) == 0 {
|
||||
fail("empty declaration")
|
||||
}
|
||||
switch spec := typed.Specs[0].(type) {
|
||||
case *ast.TypeSpec:
|
||||
return spec.Name.Name, "type", ""
|
||||
case *ast.ValueSpec:
|
||||
return spec.Names[0].Name, strings.ToLower(typed.Tok.String()), ""
|
||||
}
|
||||
}
|
||||
fail("unsupported declaration %T", decl)
|
||||
return "", "", ""
|
||||
}
|
||||
|
||||
func receiverName(decl *ast.FuncDecl) string {
|
||||
if decl.Recv == nil || len(decl.Recv.List) == 0 {
|
||||
return ""
|
||||
}
|
||||
switch typed := decl.Recv.List[0].Type.(type) {
|
||||
case *ast.Ident:
|
||||
return typed.Name
|
||||
case *ast.StarExpr:
|
||||
if ident, ok := typed.X.(*ast.Ident); ok {
|
||||
return ident.Name
|
||||
}
|
||||
}
|
||||
fail("unsupported receiver for %s", decl.Name.Name)
|
||||
return ""
|
||||
}
|
||||
|
||||
func declarationStart(decl ast.Decl) token.Pos {
|
||||
start := decl.Pos()
|
||||
switch typed := decl.(type) {
|
||||
case *ast.FuncDecl:
|
||||
if typed.Doc != nil {
|
||||
start = typed.Doc.Pos()
|
||||
}
|
||||
case *ast.GenDecl:
|
||||
if typed.Doc != nil {
|
||||
start = typed.Doc.Pos()
|
||||
}
|
||||
}
|
||||
return start
|
||||
}
|
||||
|
||||
func declarationKey(item declaration) string {
|
||||
key := item.Kind + ":"
|
||||
if item.Receiver != "" {
|
||||
key += item.Receiver + "."
|
||||
}
|
||||
return key + item.Name
|
||||
}
|
||||
|
||||
func assertContains(source []byte, fragment string) {
|
||||
if !bytes.Contains(source, []byte(fragment)) {
|
||||
fail("required invariant not found: %s", fragment)
|
||||
}
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func fail(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, "R7 verification failed: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
Reference in New Issue
Block a user