]> git.giacomolli.uk - onehouse/blob - driver/m31/topology_test.go
Share the Alamo gateway request budget
[onehouse] / driver / m31 / topology_test.go
1 package m31
2
3 import (
4 "testing"
5 "time"
6
7 "github.com/stretchr/testify/require"
8
9 "onehouse/protocol"
10 )
11
12 func TestTopologyKeepsIndependentAddressRanges(t *testing.T) {
13 value, err := newTopology([]Module{
14 {Model: HostModel},
15 {Model: OutputModel, PulseWidths: map[int]time.Duration{15: 200 * time.Millisecond}},
16 {Model: AnalogModel},
17 {Model: InputModel},
18 {Model: MixedModel},
19 {Model: AnalogModel},
20 })
21 require.NoError(t, err)
22 require.Len(t, value.inputs, 32)
23 require.Len(t, value.outputs, 32)
24 require.Len(t, value.analog, 16)
25 require.Equal(t, "m4.di0", value.inputs[24].id)
26 require.Equal(t, "m4.do0", value.outputs[24].id)
27 require.EqualValues(t, 24, value.outputs[24].address)
28 require.Equal(t, "m5.ao0", value.analog[8].id)
29 require.EqualValues(t, 8, value.analog[8].address)
30 require.EqualValues(t, 200, value.outputs[23].pulse)
31
32 descriptor := value.descriptor()
33 require.Len(t, descriptor.Capabilities, 80)
34
35 for _, capability := range descriptor.Capabilities {
36 if capability.ID == "m1.do15" {
37 require.Equal(t, "pulse", capability.Type)
38 require.False(t, capability.ReportsState)
39 require.True(t, capability.AcceptsCommands)
40 }
41 }
42
43 id, err := protocol.NewID(time.Now())
44 require.NoError(t, err)
45
46 _, err = protocol.BuildDescriptor(id, protocol.Metadata{MessageID: id}, descriptor)
47 require.NoError(t, err)
48 }
49
50 func TestTopologyRejectsUnsafeModulesAndPulseSettings(t *testing.T) {
51 testCases := []struct {
52 name string
53 modules []Module
54 }{
55 {name: "requires a host"},
56 {name: "limits total modules", modules: make([]Module, 17)},
57 {name: "rejects unknown models", modules: []Module{{Model: "unknown"}}},
58 {name: "rejects expansion at slot zero", modules: []Module{{Model: MixedModel}}},
59 {name: "rejects another host", modules: []Module{{Model: HostModel}, {Model: HostModel}}},
60 {name: "rejects negative pulse channel", modules: []Module{{Model: HostModel, PulseWidths: map[int]time.Duration{-1: time.Second}}}},
61 {name: "rejects excess pulse channel", modules: []Module{{Model: HostModel, PulseWidths: map[int]time.Duration{8: time.Second}}}},
62 {name: "rejects pulse on input module", modules: []Module{{Model: HostModel}, {Model: InputModel, PulseWidths: map[int]time.Duration{0: time.Second}}}},
63 {name: "rejects short pulse", modules: []Module{{Model: HostModel, PulseWidths: map[int]time.Duration{0: time.Millisecond}}}},
64 {name: "rejects long pulse", modules: []Module{{Model: HostModel, PulseWidths: map[int]time.Duration{0: 65536 * time.Millisecond}}}},
65 {name: "rejects fractional millisecond", modules: []Module{{Model: HostModel, PulseWidths: map[int]time.Duration{0: 50*time.Millisecond + time.Nanosecond}}}},
66 }
67
68 for _, tc := range testCases {
69 t.Run(tc.name, func(t *testing.T) {
70 _, err := newTopology(tc.modules)
71 require.Error(t, err)
72 })
73 }
74 }