module WidthInfererTests open CommonTypes open CanvasStates open CanvasStatesWithBuses type private WidthInfererTestCaseInput = CanvasState type private WidthInfererTestCaseOutput = Result type private WidhtInfererTestCase = string * WidthInfererTestCaseInput * WidthInfererTestCaseOutput let private testCasesWidthInfererSimple : WidhtInfererTestCase list = [ "Two unconnected input nodes. No conections", state2, Ok Map.empty "Simple circuit with one input connected to one output", state3, [ ConnectionId "conn0", Some 1 ] |> Map.ofList |> Ok "Simple circuit with one input connected to two outputs", state4, [ ConnectionId "conn0", Some 1 ConnectionId "conn1", Some 1 ] |> Map.ofList |> Ok "Two inputs; one And; one output", state6, [ ConnectionId "conn0", Some 1 ConnectionId "conn1", Some 1 ConnectionId "conn2", Some 1 ] |> Map.ofList |> Ok "Partially connected and: missing bottom connections", state25, [ ConnectionId "conn0", Some 1 ConnectionId "conn2", Some 1 ] |> Map.ofList |> Ok "Partially connected and: missing connection to output", state26, [ ConnectionId "conn0", Some 1 ConnectionId "conn1", Some 1 ] |> Map.ofList |> Ok "Partially connected and: missing both input connections", state27, [ ConnectionId "conn2", Some 1 ] |> Map.ofList |> Ok "One input and one output, connected to the state3CustomComponent", state16, [ ConnectionId "conn0", Some 1 ConnectionId "conn1", Some 1 ] |> Map.ofList |> Ok "Nested custom components", state18, [ ConnectionId "conn0", Some 1 ConnectionId "conn1", Some 1 ] |> Map.ofList |> Ok ] let private testCasesWidthInfererBuses : WidhtInfererTestCase list = [ "Two inputs connected to a MergeWires component. No other connections", stateBus1, [ ConnectionId "conn0", Some 1 ConnectionId "conn1", Some 1 ] |> Map.ofList |> Ok "A MergeWires connected to a SplitWire 1.", stateBus2, [ ConnectionId "conn0", None ] |> Map.ofList |> Ok "A MergeWires connected to a SplitWire 1 and a single-bit output node", stateBus3, [ ConnectionId "conn0", None ConnectionId "conn1", None ] |> Map.ofList |> Ok "A MergeWires connected to a SplitWire 1, with loop", stateBus4, [ ConnectionId "conn0", None ConnectionId "conn1", None ] |> Map.ofList |> Ok "All the bus components in series, properly connected. No other components", stateBus6, [ ConnectionId "conn0", None ConnectionId "conn1", None ConnectionId "conn2", None ConnectionId "conn3", None ConnectionId "conn4", None ] |> Map.ofList |> Ok "Non-inferrable loop", stateBus7, [ ConnectionId "conn0", None ConnectionId "conn1", None ] |> Map.ofList |> Ok "Mux connected to two MergeWires. Width not inferrable", stateBus8, [ ConnectionId "conn0", None ConnectionId "conn1", None ] |> Map.ofList |> Ok "A 4 bit input connected to a four bit output", stateBus13, [ ConnectionId "conn", Some 4 ] |> Map.ofList |> Ok "A 2 bit input split into 2 single bit outputs", stateBus16, [ ConnectionId "conn0", Some 2 ConnectionId "conn1", Some 1 ConnectionId "conn2", Some 1 ] |> Map.ofList |> Ok "3 bit input merged with 4 bit input, then split in the same way", stateBus17, [ ConnectionId "678ffa07-0ed7-7b6f-ba9b-b14839c08a71", Some 7 ConnectionId "7438de0c-bbaf-c1f6-0307-42ece66c6c00", Some 4 ConnectionId "82cc4ce9-7b15-40ac-0226-98a7f8e2fb9a", Some 4 ConnectionId "9df32195-00b4-9795-3dc1-78fb70d453f2", Some 3 ConnectionId "cd13c70f-6037-0cf4-1295-5795e92d745c", Some 3 ] |> Map.ofList |> Ok "Partially connected Mux2", stateBus18, [ ConnectionId "conn-sel", Some 1 ConnectionId "conn-top-input", Some 2 ConnectionId "conn-to-output", Some 2 ] |> Map.ofList |> Ok "Partially connected Demux2", stateBus20, [ ConnectionId "conn-to-input", Some 2 ConnectionId "conn-to-output", Some 2 ] |> Map.ofList |> Ok ] let private testCasesWidthInfererError : WidhtInfererTestCase list = [ "Two inputs connected to the same output", state5, Error { Msg = "A wire must have precisely one driving component. If you want to merge two wires together, use a MergeWires component." ConnectionsAffected = ["conn1"; "conn0"] |> List.map ConnectionId } "Two inputs; one And; one output; with extra connection input to output", state7, Error { Msg = "A wire must have precisely one driving component. If you want to merge two wires together, use a MergeWires component." ConnectionsAffected = ["conn3"; "conn2"] |> List.map ConnectionId } "And connected to a SplitWire 1", stateBus9, Error { Msg = "Wrong wire width. Target port expects a signal with at least 2 bits, but source port produces a 1 bit(s) signal." ConnectionsAffected = ["conn0"] |> List.map ConnectionId } "A 4 bit input connected to a 3 bit output", stateBus14, Error { Msg = "Wrong wire width. Target port expects a 3 bit(s) signal, but source port produces a 4 bit(s) signal." ConnectionsAffected = ["conn"] |> List.map ConnectionId } "A 3 bit input connected to a 4 bit output", stateBus15, Error { Msg = "Wrong wire width. Target port expects a 4 bit(s) signal, but source port produces a 3 bit(s) signal." ConnectionsAffected = ["conn"] |> List.map ConnectionId } "Fully connected Mux, but two inputs have different widths", stateBus19, Error { Msg = "Wrong wire width. The two inputs to a multiplexer are expected to have the same width, but top input has 2 bits and bottom input has 1 bits." ConnectionsAffected = ["conn-top-input"; "conn-bottom-input"] |> List.map ConnectionId } ] let testCasesWidthInferer : WidhtInfererTestCase list = testCasesWidthInfererSimple @ testCasesWidthInfererBuses @ testCasesWidthInfererError