Review round 1: the decoder type ships before any composer can emit it, so a routine SDK bump never sends yields to an engine that refuses them; the composer half moves to a later change. Every yielding process of a node goes into one top-level slice, meshyield.slice, so the three build modules share one quota instead of taking one each; the share is one node value, node-tools' build-cpu-share, and each step's threads divide it by every build slot of the node (words from the composer, a conservative fallback without them).
54 lines
1.9 KiB
Go
54 lines
1.9 KiB
Go
package buildstep
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// 1887/A7: the node's build capacity is the build module's setting, read at every pull: the control-node at 0 pulls
|
|
// nothing, a change takes effect at the next read, and a setting that cannot be read pulls nothing.
|
|
func TestNodeCapacity(t *testing.T) {
|
|
if got := NodeCapacity("", DefaultCapacities, "novox", nil)(); got != 0 {
|
|
t.Errorf("novox = %d by default, want 0", got)
|
|
}
|
|
if got := NodeCapacity("", DefaultCapacities, "shanks", nil)(); got != 3 {
|
|
t.Errorf("shanks = %d by default, want 3", got)
|
|
}
|
|
file := filepath.Join(t.TempDir(), "settings.json")
|
|
os.WriteFile(file, []byte(`{"capacity":"shanks=1,ace=2"}`), 0o600)
|
|
capacity := NodeCapacity(file, DefaultCapacities, "shanks", nil)
|
|
if got := capacity(); got != 1 {
|
|
t.Errorf("shanks = %d from the file, want 1", got)
|
|
}
|
|
os.WriteFile(file, []byte(`{"capacity":"shanks=4"}`), 0o600)
|
|
if got := capacity(); got != 4 {
|
|
t.Errorf("shanks = %d after the change, want 4", got)
|
|
}
|
|
if got := NodeCapacity(file, "", "pi", nil)(); got != 1 {
|
|
t.Errorf("a node not named = %d, want 1", got)
|
|
}
|
|
os.WriteFile(file, []byte(`{"capacity":"shanks=lots"}`), 0o600)
|
|
if got := capacity(); got != 0 {
|
|
t.Errorf("an unreadable setting = %d, want 0", got)
|
|
}
|
|
if got := NodeCapacity(filepath.Join(t.TempDir(), "none"), DefaultCapacities, "shanks", nil)(); got != 0 {
|
|
t.Errorf("a missing file = %d, want 0", got)
|
|
}
|
|
}
|
|
|
|
// ADR 0553 §4: a step's limits come from the composer's words; without them, every build seat at the module's own
|
|
// capacity at the default share.
|
|
func TestNodeLimits(t *testing.T) {
|
|
t.Setenv("MESH_BUILD_CPU_SHARE", "")
|
|
t.Setenv("MESH_BUILD_SLOTS", "")
|
|
if l := NodeLimits(3); l.Percent != 50 || l.Slots != 9 {
|
|
t.Errorf("without words: %+v", l)
|
|
}
|
|
t.Setenv("MESH_BUILD_CPU_SHARE", "75")
|
|
t.Setenv("MESH_BUILD_SLOTS", "5")
|
|
if l := NodeLimits(3); l.Percent != 75 || l.Slots != 5 || l.Threads < 1 {
|
|
t.Errorf("from the words: %+v", l)
|
|
}
|
|
}
|