open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-hydra-client/clients/go/jclaw_hydra_test.go
Transaction Science 0c14dc33c8 jouleclaw-hydra-client: a transport's joule figure carries its grade; ungraded is an estimate
The client sealed any transport-supplied joules figure as HwShunt, in
all three clients (Rust lib.rs, Go jclaw_hydra.go, Python client.py),
though TransportResponse.joules_uj carries no grade: a transport with an
estimate, or a figure of unknown origin, had it sealed as a hardware
reading.

TransportResponse now carries the grade of the meter that produced the
figure (Rust joules_provenance: Option<Provenance>, plus with_joules;
Go JoulesProvenance string; Python joules_provenance), and one rule,
graded_joules / GradedJoules, decides what is sealed in every client:
the figure at its stated grade; an ungraded figure (or, in Go/Python, a
grade that is not HwShunt/ModelBased/Estimator) as Estimator; no figure
as a zero Estimator. The conformance vectors carry no touch and are
unchanged; Go and Python still verify 9/9.

Tests (each fails before on HwShunt): Rust an_ungraded_transport_figure_
is_sealed_as_an_estimate, a_graded_transport_figure_keeps_its_grade;
Go TestUngradedJoulesAreSealedAsEstimates, TestGradedJoulesKeepTheirGrade;
Python tests/test_energy_grade.py (pytest).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 18:03:10 -04:00

164 lines
5.1 KiB
Go

package jclawhydra
import (
"encoding/json"
"os"
"path/filepath"
"reflect"
"testing"
)
// Conformance test — load the shared vectors and assert every one
// produces a byte-equal CallReport against the Rust producer's
// expectations. BLAKE3 hashes match across Rust + Python + Go.
func shapeGraphForTests() *ShapeGraph {
min1 := 1
max1 := 1
dtString := DTString
return NewShapeGraph().Add(NodeShape{
TargetClass: "https://example.com/Tool#AppendInput",
Properties: []PropertyShape{
{Path: "parent", MinCount: &min1, MaxCount: &max1, Datatype: &dtString},
{Path: "kind", MinCount: &min1, MaxCount: &max1, Datatype: &dtString,
In: []interface{}{"blob", "text"}},
},
})
}
func loadConformance(t *testing.T) map[string]interface{} {
t.Helper()
root, err := filepath.Abs(filepath.Join("..", "..", "conformance", "call-reports.json"))
if err != nil {
t.Fatalf("abs: %v", err)
}
b, err := os.ReadFile(root)
if err != nil {
t.Fatalf("read %s: %v", root, err)
}
var doc map[string]interface{}
if err := json.Unmarshal(b, &doc); err != nil {
t.Fatalf("parse: %v", err)
}
return doc
}
func TestCallReportsConformance(t *testing.T) {
doc := loadConformance(t)
apiBytes, _ := json.Marshal(doc["api"])
api, err := ParseAPI(apiBytes)
if err != nil {
t.Fatalf("parse api: %v", err)
}
client := NewClient(api, shapeGraphForTests())
transport := NewMockTransport()
reports := doc["call_reports"].([]interface{})
for _, raw := range reports {
v := raw.(map[string]interface{})
label := v["label"].(string)
op := v["operation"].(string)
input := v["input"]
expected := v["expected"].(map[string]interface{})
got, err := client.Call(op, input, transport)
if err != nil {
t.Errorf("FAIL %s: %v", label, err)
continue
}
if exp := expected["tool_id"].(string); got.ToolID != exp {
t.Errorf("FAIL %s tool_id expected=%s got=%s", label, exp, got.ToolID)
}
if exp := int(expected["status"].(float64)); got.Status != exp {
t.Errorf("FAIL %s status expected=%d got=%d", label, exp, got.Status)
}
if exp := expected["input_hash"].(string); got.InputHash != exp {
t.Errorf("FAIL %s input_hash expected=%s got=%s", label, exp, got.InputHash)
}
if exp := expected["output_hash"].(string); got.OutputHash != exp {
t.Errorf("FAIL %s output_hash expected=%s got=%s", label, exp, got.OutputHash)
}
if exp := expected["status_matches_contract"].(bool); got.StatusMatchesContract != exp {
t.Errorf("FAIL %s status_matches expected=%v got=%v", label, exp, got.StatusMatchesContract)
}
if !reflect.DeepEqual(got.Body, expected["body"]) {
t.Errorf("FAIL %s body expected=%v got=%v", label, expected["body"], got.Body)
} else {
t.Logf("PASS %s", label)
}
}
}
func TestValidationConformance(t *testing.T) {
doc := loadConformance(t)
apiBytes, _ := json.Marshal(doc["api"])
api, _ := ParseAPI(apiBytes)
client := NewClient(api, shapeGraphForTests())
cases, ok := doc["validation_reports"].([]interface{})
if !ok {
t.Skip("no validation_reports")
}
for _, raw := range cases {
v := raw.(map[string]interface{})
label := v["label"].(string)
opName := v["operation"].(string)
input := v["input"]
expected := v["expected_conforms"].(bool)
op := client.FindOperation(opName)
if op == nil {
t.Errorf("FAIL %s op-not-found", label)
continue
}
err := client.ValidateInput(op, input)
conforms := err == nil
if conforms != expected {
t.Errorf("FAIL %s validation expected=%v got=%v err=%v", label, expected, conforms, err)
} else {
t.Logf("PASS %s", label)
}
}
}
// A transport's joule figure says nothing of how it was obtained: an
// ungraded figure is sealed as an estimate, never as a hardware reading.
func TestUngradedJoulesAreSealedAsEstimates(t *testing.T) {
doc := loadConformance(t)
apiBytes, _ := json.Marshal(doc["api"])
api, err := ParseAPI(apiBytes)
if err != nil {
t.Fatalf("parse api: %v", err)
}
client := NewClient(api, shapeGraphForTests())
reports := doc["call_reports"].([]interface{})
v := reports[0].(map[string]interface{})
op := v["operation"].(string)
opID := client.FindOperation(op).ID
seven := uint64(7)
transport := NewMockTransport().Respond(opID, &TransportResponse{Status: 200, Body: map[string]interface{}{}, JoulesUJ: &seven})
got, err := client.Call(op, v["input"], transport)
if err != nil {
t.Fatalf("call: %v", err)
}
if got.Touch["joules_uj"] != uint64(7) || got.Touch["energy_provenance"] != "Estimator" {
t.Errorf("an ungraded figure sealed as %v", got.Touch)
}
}
// A graded figure keeps the grade the transport gave it.
func TestGradedJoulesKeepTheirGrade(t *testing.T) {
nine := uint64(9)
for _, grade := range []string{"HwShunt", "ModelBased", "Estimator"} {
r := &TransportResponse{JoulesUJ: &nine, JoulesProvenance: grade}
if uj, p := r.GradedJoules(); uj != 9 || p != grade {
t.Errorf("%s: sealed %d %s", grade, uj, p)
}
}
if _, p := (&TransportResponse{JoulesUJ: &nine, JoulesProvenance: "Measured"}).GradedJoules(); p != "Estimator" {
t.Errorf("an unknown grade sealed as %s", p)
}
if uj, p := (&TransportResponse{JoulesProvenance: "HwShunt"}).GradedJoules(); uj != 0 || p != "Estimator" {
t.Errorf("no figure sealed as %d %s", uj, p)
}
}