chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package contractgovernance
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDeviceContractCompatibilityGuardrails(t *testing.T) {
|
||||
root := repositoryRoot(t)
|
||||
contract := readFile(t, filepath.Join(root, "openapi", "openapi.yaml"))
|
||||
|
||||
versions := regexp.MustCompile(`(?m)^ /device/v([0-9]+)(?:/[^:]+)?:$`).FindAllStringSubmatch(contract, -1)
|
||||
if len(versions) < 10 {
|
||||
t.Fatalf("found only %d versioned device paths; contract scan likely stopped matching", len(versions))
|
||||
}
|
||||
for _, match := range versions {
|
||||
if match[1] != "2" {
|
||||
t.Fatalf("device path %q bypasses the current v2 compatibility baseline", match[0])
|
||||
}
|
||||
}
|
||||
for _, required := range []string{
|
||||
"rtc_credential_renewal:",
|
||||
"省略时保持旧版v2终端行为",
|
||||
"设备不得据此改变采集、编码、发布、订阅或播放逻辑",
|
||||
} {
|
||||
if !strings.Contains(contract, required) {
|
||||
t.Fatalf("OpenAPI is missing device compatibility rule %q", required)
|
||||
}
|
||||
}
|
||||
contractVersion := regexp.MustCompile(`(?m)^ version: ([0-9]+\.[0-9]+\.[0-9]+)$`).FindStringSubmatch(contract)
|
||||
if len(contractVersion) != 2 {
|
||||
t.Fatal("OpenAPI info.version must be a semantic version")
|
||||
}
|
||||
|
||||
notes := readFile(t, filepath.Join(root, "docs", "device-api-compatibility.md"))
|
||||
if !strings.Contains(notes, "当前接口契约:OpenAPI "+contractVersion[1]) || !strings.Contains(notes, "/device/v2") || !strings.Contains(notes, "/device/v3") {
|
||||
t.Fatal("device compatibility notes are not synchronized with the current contract and next breaking version")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeviceBehaviorDoesNotDependOnUserAgentOrEngineMode(t *testing.T) {
|
||||
root := repositoryRoot(t)
|
||||
for _, relative := range []string{"internal/deviceauth", "internal/httpapi", "internal/orchestration", "cmd/sim-device"} {
|
||||
directory := filepath.Join(root, filepath.FromSlash(relative))
|
||||
err := filepath.WalkDir(directory, func(path string, entry fs.DirEntry, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
return walkErr
|
||||
}
|
||||
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") || strings.HasSuffix(entry.Name(), "_test.go") {
|
||||
return nil
|
||||
}
|
||||
contents := readFile(t, path)
|
||||
for _, forbidden := range []string{`Header.Get("User-Agent")`, ".UserAgent()"} {
|
||||
if strings.Contains(contents, forbidden) {
|
||||
t.Errorf("%s uses firmware User-Agent for behavior selection", filepath.ToSlash(path))
|
||||
}
|
||||
}
|
||||
if relative == "cmd/sim-device" && strings.Contains(contents, "engine_mode") {
|
||||
t.Errorf("%s makes the terminal aware of diagnostic-only engine_mode", filepath.ToSlash(path))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("scan %s: %v", relative, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func repositoryRoot(t *testing.T) string {
|
||||
t.Helper()
|
||||
_, current, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
t.Fatal("resolve contract test location")
|
||||
}
|
||||
return filepath.Clean(filepath.Join(filepath.Dir(current), "..", ".."))
|
||||
}
|
||||
|
||||
func readFile(t *testing.T, path string) string {
|
||||
t.Helper()
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("read %s: %v", path, err)
|
||||
}
|
||||
return string(contents)
|
||||
}
|
||||
Reference in New Issue
Block a user