package m31 import ( "testing" "time" "github.com/stretchr/testify/require" ) func TestOutputRequestRejectsUnsafeValuesAndAccess(t *testing.T) { d, _, _, _ := testAssembly(t) testCases := []struct { name string point string value string batch bool }{ {name: "rejects null Boolean", point: "m0.do0", value: "null"}, {name: "rejects numeric Boolean", point: "m0.do0", value: "1"}, {name: "rejects string Boolean", point: "m0.do0", value: `"true"`}, {name: "rejects input writes", point: "m0.di0", value: "true"}, {name: "rejects unknown points", point: "m8.do0", value: "true"}, {name: "rejects false pulses", point: "m0.do2", value: "false"}, {name: "rejects pulses in batches", point: "m0.do2", value: "true", batch: true}, {name: "rejects analog in batches", point: "m2.ao0", value: "5", batch: true}, {name: "rejects negative voltage", point: "m2.ao0", value: "-0.00000000000000001"}, {name: "rejects excessive voltage without float rounding", point: "m2.ao0", value: "10.00000000000000001"}, {name: "rejects string voltage", point: "m2.ao0", value: `"5"`}, {name: "rejects null voltage", point: "m2.ao0", value: "null"}, {name: "rejects malformed voltage", point: "m2.ao0", value: "5x"}, {name: "rejects missing voltage", point: "m2.ao0"}, {name: "rejects object voltage", point: "m2.ao0", value: "{}"}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { command := testCommand(t, tc.point, tc.value) _, reason := newOutputRequest(command, d.topology, testDeviceID, tc.batch) require.NotEmpty(t, reason) }) } command := testCommand(t, "m0.do0", "true") command.DeviceID = "01ARZ3NDEKTSV4RRFFQ69G5FAW" _, reason := newOutputRequest(command, d.topology, testDeviceID, false) require.Contains(t, reason, "another device") command.DeviceID = testDeviceID expires := time.Now() command.Metadata.ExpiresAt = &expires _, reason = newOutputRequest(command, d.topology, testDeviceID, false) require.Contains(t, reason, "expired") } func TestOutputRequestRoundsValidVoltageToMillivolts(t *testing.T) { d, _, _, _ := testAssembly(t) testCases := []struct { name string value string want uint16 }{ {name: "accepts zero", value: "0"}, {name: "accepts full range", value: "10", want: 10000}, {name: "rounds half millivolt up", value: "5.5005", want: 5501}, {name: "accepts exponent notation", value: "55e-1", want: 5500}, {name: "accepts surrounding whitespace", value: " 5.5 ", want: 5500}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { request, reason := newOutputRequest(testCommand(t, "m2.ao0", tc.value), d.topology, testDeviceID, false) require.Empty(t, reason) require.Equal(t, tc.want, request.value) }) } }