Add goTool autotest with bench configs and UART scenarios.

JSON configs describe network and node MACs; scenarios run command
sequences with expect checks. Share UART client API across CLI and tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-18 23:36:28 +02:00
co-authored by Cursor
parent a8ae65d9dc
commit d24b0cb5c3
17 changed files with 958 additions and 106 deletions
+69
View File
@@ -0,0 +1,69 @@
package autotest
import (
"encoding/json"
"fmt"
"os"
)
// Scenario is an ordered list of steps run against a bench Config.
type Scenario struct {
ID string `json:"id"`
Description string `json:"description,omitempty"`
ConfigID string `json:"config"`
Steps []Step `json:"steps"`
}
type Step struct {
Name string `json:"name,omitempty"`
Command string `json:"command,omitempty"`
DelayMS int `json:"delay_ms,omitempty"`
Input json.RawMessage `json:"input,omitempty"`
Expect Expect `json:"expect,omitempty"`
}
type Expect struct {
// version
Version *uint32 `json:"version,omitempty"`
VersionMin *uint32 `json:"version_min,omitempty"`
GitHash string `json:"git_hash,omitempty"`
// clients
MinClients *int `json:"min_clients,omitempty"`
MaxClients *int `json:"max_clients,omitempty"`
ClientCount *int `json:"client_count,omitempty"`
Slave string `json:"slave,omitempty"`
Slaves []string `json:"slaves,omitempty"`
Available *bool `json:"available,omitempty"`
MAC string `json:"mac,omitempty"`
// deadzone
Deadzone *uint32 `json:"deadzone,omitempty"`
Success *bool `json:"success,omitempty"`
SlavesUpdated *uint32 `json:"slaves_updated,omitempty"`
SlavesUpdatedMin *uint32 `json:"slaves_updated_min,omitempty"`
// unicast_test
Seq *uint32 `json:"seq,omitempty"`
}
func LoadScenario(path string) (*Scenario, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var sc Scenario
if err := json.Unmarshal(data, &sc); err != nil {
return nil, fmt.Errorf("parse scenario: %w", err)
}
if sc.ID == "" {
return nil, fmt.Errorf("scenario: id is required")
}
if sc.ConfigID == "" {
return nil, fmt.Errorf("scenario %q: config is required", sc.ID)
}
if len(sc.Steps) == 0 {
return nil, fmt.Errorf("scenario %q: no steps", sc.ID)
}
return &sc, nil
}