mesh/delivery-group group feat/sdk1 rejected: composed together: the checker's verdict at the members' heads (428d048dd50a): unit: git.novox.be/novox/mesh-sdk/…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: unit: git.novox.be/novox/mesh-sdk/go/process.TestStatePutWritesAKeyWhole: a Put through a short blackout: 0, mesh-mail's state send…
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
130 lines
3.8 KiB
Go
130 lines
3.8 KiB
Go
package catalogue
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"strconv"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// Defends novox/hq ADR 0255: a seat may receive a kind as data in its own shape, which the holder
|
||
// renders with its template; the holder places every combination of the shape's placing fields once;
|
||
// a contribution may be placed only where the machine reports a capability; and an offered kind makes
|
||
// no dependency on its seat.
|
||
|
||
const barTemplate = `{{if eq .shows "battery"}}[[block]]
|
||
block = "battery"
|
||
{{with .options}}{{with .device}}device = {{quote .}}
|
||
{{end}}{{end}}{{else if eq .shows "command"}}[[block]]
|
||
block = "custom"
|
||
command = {{quote .options.command}}
|
||
interval = {{.options.interval}}
|
||
{{else if eq .shows "state"}}[[block]]
|
||
block = "custom"
|
||
command = {{quote (printf "show %s %s" .options.state (or .options.key .machine))}}
|
||
{{end}}`
|
||
|
||
func barHolder() Manifest {
|
||
place := func(bar string) string {
|
||
return "own-first\n${contribution:node-bar:block:bar=" + bar + ",place=resources}" +
|
||
"own-middle\n${contribution:node-bar:block:bar=" + bar + ",place=status}own-last\n"
|
||
}
|
||
return Manifest{Module: "a-bar", Claims: []Claim{{Name: BarSeat, Renders: map[string]string{BarKindBlock: barTemplate}}},
|
||
Resources: []map[string]any{
|
||
{"id": "bottom", "type": "file", "path": "/b", "content": place("bottom")},
|
||
{"id": "top", "type": "file", "path": "/t", "content": place("top")},
|
||
}}
|
||
}
|
||
|
||
func block(data string) SeatContribution {
|
||
var d map[string]any
|
||
if err := json.Unmarshal([]byte(data), &d); err != nil {
|
||
panic(err)
|
||
}
|
||
return SeatContribution{Seat: BarSeat, Kind: BarKindBlock, Data: d}
|
||
}
|
||
|
||
// tomlBasicString reads one TOML basic string, as the TOML specification (1.0, "String") defines it:
|
||
// any character but a quote, a backslash and the control characters U+0000–U+0008, U+000A–U+001F
|
||
// and U+007F, which are written as escapes.
|
||
func tomlBasicString(s string) (string, error) {
|
||
if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
|
||
return "", fmt.Errorf("not quoted")
|
||
}
|
||
var b strings.Builder
|
||
rs := []rune(s[1 : len(s)-1])
|
||
for i := 0; i < len(rs); i++ {
|
||
r := rs[i]
|
||
switch {
|
||
case r == '"':
|
||
return "", fmt.Errorf("a bare quote at %d", i)
|
||
case r == 0x7f || (r < 0x20 && r != '\t'):
|
||
return "", fmt.Errorf("a bare control character %U at %d", r, i)
|
||
case r != '\\':
|
||
b.WriteRune(r)
|
||
continue
|
||
}
|
||
i++
|
||
if i >= len(rs) {
|
||
return "", fmt.Errorf("an escape at the end")
|
||
}
|
||
switch rs[i] {
|
||
case 'b':
|
||
b.WriteRune('\b')
|
||
case 't':
|
||
b.WriteRune('\t')
|
||
case 'n':
|
||
b.WriteRune('\n')
|
||
case 'f':
|
||
b.WriteRune('\f')
|
||
case 'r':
|
||
b.WriteRune('\r')
|
||
case '"':
|
||
b.WriteRune('"')
|
||
case '\\':
|
||
b.WriteRune('\\')
|
||
case 'u', 'U':
|
||
n := 4
|
||
if rs[i] == 'U' {
|
||
n = 8
|
||
}
|
||
if i+n > len(rs)-1 {
|
||
return "", fmt.Errorf("a short \\u escape")
|
||
}
|
||
v, err := strconv.ParseUint(string(rs[i+1:i+1+n]), 16, 32)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
b.WriteRune(rune(v))
|
||
i += n
|
||
default:
|
||
return "", fmt.Errorf("the escape \\%c is not TOML's", rs[i])
|
||
}
|
||
}
|
||
return b.String(), nil
|
||
}
|
||
|
||
func TestTheBarReceivesBlocksAsData(t *testing.T) {
|
||
s, _ := SeatNamed(BarSeat)
|
||
if len(s.Receives) != 1 || s.Receives[0].Kind != BarKindBlock || s.Receives[0].Shape == nil || !s.Receives[0].Offered {
|
||
t.Fatalf("node-bar receives %+v", s.Receives)
|
||
}
|
||
for _, ex := range s.Receives[0].Shape.Examples {
|
||
if p := barBlockProblems(ex); len(p) > 0 {
|
||
t.Errorf("the shape's own example %v is refused: %v", ex, p)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestPerMachineStateIsDeclaredAndKeptInItsLongForm(t *testing.T) {
|
||
m, err := decodeForTest([]byte(`{"module":"power","state":[{"name":"draw","ttl-seconds":30,"per-machine":true}]}`))
|
||
if err != nil || len(m.State) != 1 || !m.State[0].PerMachine {
|
||
t.Fatalf("%+v %v", m.State, err)
|
||
}
|
||
raw, _ := json.Marshal(StateDeclaration{Name: "draw", PerMachine: true})
|
||
if string(raw) != `{"name":"draw","per-machine":true}` {
|
||
t.Fatalf("%s", raw)
|
||
}
|
||
}
|