def test_replace_graph():
    plumb0 = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                  utils.CLOSED)
    plumb = test.two_valve_setup(0, 0, utils.CLOSED, utils.CLOSED, 0, 0,
                                 utils.CLOSED, utils.CLOSED)

    pressures = {3: (100, False)}
    default_states = {'valve1': 'closed', 'valve2': 'open'}
    plumb.load_graph(plumb0.component_dict, plumb0.mapping, pressures,
                     default_states)

    assert plumb.time_res == int(
        utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE)
    assert plumb.edges() == [(1, 2, 'valve1.A1', {
        'FC': utils.teq_to_FC(utils.s_to_micros(10))
    }), (2, 1, 'valve1.A2', {
        'FC': 0
    }), (2, 3, 'valve2.B1', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
    }), (3, 2, 'valve2.B2', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
    })]
    assert plumb.nodes() == [(1, {
        'body': top.GenericNode(0)
    }), (2, {
        'body': top.GenericNode(0)
    }), (3, {
        'body': top.GenericNode(100)
    })]
    assert plumb.current_state('valve1') == 'closed'
    assert plumb.current_state('valve2') == 'open'
def test_misc_engine():
    steady_by = utils.s_to_micros(1)
    converged = {1: 33, 2: 33, 3: 33}

    solve_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    solve_state = solve_plumb.solve()
    step_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    step_state = step_plumb.step(steady_by)
    len_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    solve_len = len(len_plumb.solve(return_resolution=len_plumb.time_res))
    test.validate_plumbing_engine(step_plumb, solve_plumb, steady_by,
                                  converged, solve_state, step_state,
                                  solve_len, len_plumb.time_res)
def test_timeout():
    converged = {1: 33, 2: 33, 3: 33}

    big_teq = 100
    plumb = test.two_valve_setup(big_teq, big_teq, big_teq, big_teq, big_teq,
                                 big_teq, big_teq, big_teq)

    solve_state = plumb.solve(max_time=1)
    assert solve_state != converged

    plumb_long = test.two_valve_setup(big_teq, big_teq, big_teq, big_teq,
                                      big_teq, big_teq, big_teq, big_teq)
    solve_len = len(
        plumb_long.solve(max_time=1, return_resolution=plumb_long.time_res))
    assert solve_len == utils.s_to_micros(1) / plumb_long.time_res
def test_set_pressure():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)
    pc = test.create_component(0, 0, 0, 1, 'valve3', 'C')
    mapping = {1: 3, 2: 4}
    plumb.add_component(pc, mapping, 'closed', {4: (50, False)})

    plumb.set_pressure(1, 200)
    plumb.set_pressure(2, 7000)

    assert plumb.nodes() == [(1, {
        'body': top.GenericNode(200)
    }), (2, {
        'body': top.GenericNode(7000)
    }), (3, {
        'body': top.GenericNode(100)
    }), (4, {
        'body': top.GenericNode(50)
    })]

    plumb.set_pressure(4, 10)
    plumb.set_pressure(1, 0)

    assert plumb.nodes() == [(1, {
        'body': top.GenericNode(0)
    }), (2, {
        'body': top.GenericNode(7000)
    }), (3, {
        'body': top.GenericNode(100)
    }), (4, {
        'body': top.GenericNode(10)
    })]
def test_reverse_orientation_three_edges():
    pc_states = {
        'open': {
            (1, 2, 'A1'): 5,
            (2, 1, 'A2'): 0,
            (1, 3, 'B1'): 3,
            (3, 1, 'B2'): 0,
            (2, 3, 'C1'): 4,
            (3, 2, 'C2'): 5
        }
    }
    pc_edges = [(1, 2, 'A1'), (2, 1, 'A2'), (1, 3, 'B1'), (3, 1, 'B2'),
                (2, 3, 'C1'), (3, 2, 'C2')]
    pc = top.PlumbingComponent('threeway', pc_states, pc_edges)

    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    mapping = {1: 3, 2: 4, 3: 5}
    plumb.add_component(pc, mapping, 'open')

    with pytest.raises(exceptions.InvalidComponentError) as err:
        plumb.reverse_orientation('threeway')
    assert str(err.value) == "Component must only have two edges to be automatically reversed.\n" +\
        "Consider adjusting direction manually."
def test_reverse_orientation():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)
    plumb.reverse_orientation('valve1')

    assert plumb.is_valid()
    assert plumb.time_res == int(
        utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE)
    assert plumb.edges() == [(1, 2, 'valve1.A1', {
        'FC': 0
    }), (2, 1, 'valve1.A2', {
        'FC': utils.teq_to_FC(utils.s_to_micros(10))
    }), (2, 3, 'valve2.B1', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
    }), (3, 2, 'valve2.B2', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
    })]
    assert plumb.nodes() == [
        (1, {
            'body': top.GenericNode(0)
        }),
        (2, {
            'body': top.GenericNode(0)
        }),
        (3, {
            'body': top.GenericNode(100)
        }),
    ]
    assert plumb.current_state('valve1') == 'closed'
    assert plumb.current_state('valve2') == 'open'
def test_add_invalid_component():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    wrong_node = 5
    pc_states = {
        'open': {
            (1, wrong_node, 'A1'): 0,
            (2, 1, 'A2'): 0
        },
        'closed': {
            (1, 2, 'A1'): 0,
            (2, 1, 'A2'): 0
        }
    }
    pc_edges = [(1, 2, 'A1'), (2, 1, 'A2')]
    invalid_pc = top.PlumbingComponent('valve', pc_states, pc_edges)

    assert not invalid_pc.is_valid()

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.add_component(invalid_pc, {1: 3, 2: 4}, 'open')
    assert str(
        err.value
    ) == "Component not valid; all errors must be resolved before loading in."
def test_reset_keep_component():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    pc = test.create_component(0, 0, 0, 1, 'valve3', 'C')
    mapping = {1: 3, 2: 4}

    plumb.add_component(pc, mapping, 'closed', {4: (50, False)})
    plumb.remove_component('valve2')
    plumb.reset()

    assert plumb.time == 0
    assert plumb.is_valid()
    assert plumb.time_res == int(
        utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE)
    assert plumb.edges() == [(1, 2, 'valve1.A1', {
        'FC': utils.teq_to_FC(utils.s_to_micros(10))
    }), (2, 1, 'valve1.A2', {
        'FC': 0
    }), (3, 4, 'valve3.C1', {
        'FC': utils.teq_to_FC(0)
    }), (4, 3, 'valve3.C2', {
        'FC': utils.teq_to_FC(utils.s_to_micros(1))
    })]
    assert plumb.nodes() == [(1, {
        'body': top.GenericNode(0)
    }), (2, {
        'body': top.GenericNode(0)
    }), (3, {
        'body': top.GenericNode(100)
    }), (4, {
        'body': top.GenericNode(0)
    })]
    assert plumb.current_state('valve1') == 'closed'
    assert plumb.current_state('valve3') == 'closed'
def test_reset_pressure():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    plumb.set_pressure(2, 150)
    plumb.reset()

    plumb_initial = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2,
                                         10, utils.CLOSED)

    assert plumb.time == 0
    assert plumb.is_valid()
    assert plumb.time_res == plumb_initial.time_res
    assert plumb.edges() == plumb_initial.edges()
    assert plumb.nodes() == plumb_initial.nodes()
    assert plumb.current_state() == plumb_initial.current_state()
def test_reset_removed_component():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    plumb.remove_component('valve2')
    plumb.reset(True)

    plumb_initial = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2,
                                         10, utils.CLOSED)

    assert plumb.time == 0
    assert plumb.is_valid()
    assert plumb.time_res == plumb_initial.time_res
    assert plumb.edges() == plumb_initial.edges()
    assert plumb.nodes() == plumb_initial.nodes()
    assert plumb.current_state() == plumb_initial.current_state()
Esempio n. 11
0
def make_plumb():
    """
    The engine that's been set up looks like this:
    +-----+           +-----+           +-----+           +-----+
    |     |  --C-->   |     |  --40->   |     |  --5-->   |     |
    |  1  |           |  2  |           |  3  |           | atm |
    |     |  <-10--   |     |  <-45--   |     |  <-5---   |     |
    +-----+           +-----+           +-----+           +-----+
    100               100                100                 0

    Result annotation:
    - node 1 stays at 100 the entire duration because 1->2 is closed, so no pressure can flow out
        of node 1.

    - node 3's pressure drops much more quickly than node 2's because its teq to atm (5) is much
        lower than the teq in the 2->3 connection (50). Pressure from 3 flows into atm much faster
        than it's replenished by pressure from 2.

    - pressure at atm stays at 0, because pressure at atm is always 0.

    """

    ret = test.two_valve_setup(1, 1, utils.CLOSED, 10, 40, 45, 1, 1)
    comp = test.create_component(5, 5, utils.CLOSED, utils.CLOSED, 'vent', 'A')
    mapping = {
        1: 3,
        2: utils.ATM,
    }
    ret.add_component(comp, mapping, 'open')
    ret.set_pressure(1, 100)
    ret.set_pressure(2, 100)
    return ret
def test_closed_engine():
    plumb = test.two_valve_setup(utils.CLOSED, utils.CLOSED, utils.CLOSED,
                                 utils.CLOSED, utils.CLOSED, utils.CLOSED,
                                 utils.CLOSED, utils.CLOSED)
    state = plumb.step()
    assert state == {1: 0, 2: 0, 3: 100}
    state = plumb.solve()
    assert state == {1: 0, 2: 0, 3: 100}
def test_fix_node():
    plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)

    assert plumb.fixed_pressures == {}

    plumb.set_pressure(3, 100, True)

    assert plumb.fixed_pressures == {3: 100}
def test_reverse_orientation_wrong_component():
    wrong_name = 'potato'
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.reverse_orientation(wrong_name)
    assert str(
        err.value) == f"Component '{wrong_name}' not found in component dict."
def test_remove_nonexistent_component():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)
    nonexistent_component = 'potato'

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.remove_component(nonexistent_component)
    assert str(err.value) ==\
        f"Component with name {nonexistent_component} not found in component dict."
def test_set_component_wrong_component_name():
    wrong_component_name = 'potato'
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.set_component_state(wrong_component_name, 'open')
    assert str(
        err.value
    ) == f"Component '{wrong_component_name}' not found in mapping dict."
def test_set_pressure_errors():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    pc = test.create_component(0, 0, 0, 1, 'valve3', 'C')
    mapping = {1: 3, 2: 4}
    plumb.add_component(pc, mapping, 'closed', {4: (50, False)})

    pc_vent = test.create_component(0, 0, 0, 0, 'vent', 'D')
    mapping_vent = {1: 4, 2: utils.ATM}
    plumb.add_component(pc_vent, mapping_vent, 'closed')

    negative_pressure = -20
    not_a_number = 'potato'
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.set_pressure(4, negative_pressure)
    assert str(
        err.value) == f"Negative pressure {negative_pressure} not allowed."

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.set_pressure(4, not_a_number)
    assert str(err.value) == f"Pressure {not_a_number} must be a number."

    assert plumb.nodes() == [(1, {
        'body': top.GenericNode(0)
    }), (2, {
        'body': top.GenericNode(0)
    }), (3, {
        'body': top.GenericNode(100)
    }), (4, {
        'body': top.GenericNode(50)
    }), (utils.ATM, {
        'body': top.AtmNode()
    })]

    nonexistent_node = 5
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.set_pressure(nonexistent_node, 100)
    assert str(err.value) == f"Node {nonexistent_node} not found in graph."

    plumb.set_pressure(4, 100)
    assert plumb.nodes() == [(1, {
        'body': top.GenericNode(0)
    }), (2, {
        'body': top.GenericNode(0)
    }), (3, {
        'body': top.GenericNode(100)
    }), (4, {
        'body': top.GenericNode(100)
    }), (utils.ATM, {
        'body': top.AtmNode()
    })]

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.set_pressure(utils.ATM, 100)
    assert str(
        err.value) == f"Pressure for atmosphere node ({utils.ATM}) must be 0."
def test_set_fixed_pressure():
    # steady_by needs to be a bit longer for this one since having the
    # fixed pressure makes equalization take longer than the teq.
    steady_by = utils.s_to_micros(3)
    converged = {1: 100, 2: 100, 3: 100}

    solve_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    solve_plumb.set_pressure(3, 100, fixed=True)
    solve_state = solve_plumb.solve()
    step_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    step_plumb.set_pressure(3, 100, fixed=True)
    step_state = step_plumb.step(steady_by)
    len_plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    len_plumb.set_pressure(3, 100, fixed=True)
    solve_len = len(len_plumb.solve(return_resolution=len_plumb.time_res))
    test.validate_plumbing_engine(step_plumb, solve_plumb, steady_by,
                                  converged, solve_state, step_state,
                                  solve_len, len_plumb.time_res)
def test_set_component_wrong_state_name():
    wrong_state_name = 'potato'
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.set_component_state('valve1', wrong_state_name)
    assert str(
        err.value
    ) == f"State '{wrong_state_name}' not found in valve1 states dict."
def test_reset_added_component():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    pc = test.create_component(0, 0, 0, 1, 'valve3', 'C')
    mapping = {1: 3, 2: 4}

    plumb.add_component(pc, mapping, 'closed', {4: (50, False)})
    plumb.reset(True)

    plumb_initial = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2,
                                         10, utils.CLOSED)

    assert plumb.time == 0
    assert plumb.is_valid()
    assert plumb.time_res == plumb_initial.time_res
    assert plumb.edges() == plumb_initial.edges()
    assert plumb.nodes() == plumb_initial.nodes()
    assert plumb.current_state() == plumb_initial.current_state()
def test_add_component_errors():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    name = 'valve3'
    wrong_node = 3
    right_node = 2
    pc = test.create_component(0, 0, 0, 1, name, 'C')
    mapping = {1: 3, wrong_node: 4}

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.add_component(pc, mapping, 'closed', {4: (50, False)})
    assert str(err.value) ==\
        f"Component '{name}', node {right_node} not found in mapping dict."
def test_components():
    plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)
    original_components = copy.deepcopy(plumb.component_dict)
    queried_components = plumb.components()

    assert list(original_components.keys()) == list(queried_components.keys())

    queried_components.pop('valve1')

    assert len(queried_components) == 1
    assert len(original_components) == 2

    # make sure that changes to the returned dict aren't propagated through to the original
    assert list(original_components.keys()) == list(plumb.component_dict.keys())
    assert list(original_components.keys()) == list(plumb.components().keys())
def test_new_component_state():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)
    plumb.set_component_state('valve1', 'open')

    assert plumb.edges() == [(1, 2, 'valve1.A1', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
    }), (2, 1, 'valve1.A2', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
    }), (2, 3, 'valve2.B1', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
    }), (3, 2, 'valve2.B2', {
        'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
    })]
    assert plumb.current_state('valve1') == 'open'
    assert plumb.current_state('valve2') == 'open'
def test_step_errors():
    plumb = test.two_valve_setup(1, 1, 1, 1, 1, 1, 1, 1)

    fl = 102482.2
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.step(fl)
    assert str(err.value) == f"timestep ({fl}) must be integer."

    too_low = 0
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.step(too_low)
    assert str(err.value) ==\
        f"timestep ({too_low}) too low, must be greater than {utils.MIN_TIME_RES_MICROS} us."

    # This shouldn't raise an error, even though 10.0 is a float
    plumb.step(1000.0)
def test_remove_add_errors():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    name = 'valve3'
    wrong_node = 3
    right_node = 2
    pc = test.create_component(0, 0, 0, 1, name, 'C')
    mapping = {1: 3, wrong_node: 4}

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.add_component(pc, mapping, 'closed', {4: (50, False)})
    assert str(err.value) ==\
        f"Component '{name}', node {right_node} not found in mapping dict."

    plumb.remove_component(name)

    assert plumb.is_valid()
    assert plumb.time_res == int(
        utils.s_to_micros(0.2) / utils.DEFAULT_RESOLUTION_SCALE)
    assert plumb.edges() == [
        (1, 2, 'valve1.A1', {
            'FC': utils.teq_to_FC(utils.s_to_micros(10))
        }),
        (2, 1, 'valve1.A2', {
            'FC': 0
        }),
        (2, 3, 'valve2.B1', {
            'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
        }),
        (3, 2, 'valve2.B2', {
            'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
        }),
    ]
    assert plumb.nodes() == [
        (1, {
            'body': top.GenericNode(0)
        }),
        (2, {
            'body': top.GenericNode(0)
        }),
        (3, {
            'body': top.GenericNode(100)
        }),
    ]
    assert plumb.current_state('valve1') == 'closed'
    assert plumb.current_state('valve2') == 'open'
def test_current_state():
    plumb = test.two_valve_setup(
        0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED)
    wrong_name = 'potato'

    assert plumb.current_state('valve1') == 'closed'
    assert plumb.current_state('valve2') == 'open'

    plumb.set_component_state('valve1', 'open')

    assert plumb.current_state('valve1') == 'open'
    assert plumb.current_state(['valve1']) == 'open'

    assert plumb.current_state() == {
        'valve1': 'open',
        'valve2': 'open'
    }

    assert plumb.current_state('valve1', 'valve2') == {
        'valve1': 'open',
        'valve2': 'open'
    }

    list_valves = ['valve1', 'valve2']
    assert plumb.current_state(list_valves) == {
        'valve1': 'open',
        'valve2': 'open'
    }

    tuple_valves = ('valve1', 'valve2')
    assert plumb.current_state(tuple_valves) == {
        'valve1': 'open',
        'valve2': 'open'
    }

    assert plumb.current_state(['valve1'], 'valve2') == {
        'valve1': 'open',
        'valve2': 'open'
    }

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.current_state(wrong_name)
    assert str(err.value) == f"Component '{wrong_name}' not found in component dict."

    with pytest.raises(exceptions.BadInputError) as err:
        plumb.current_state('valve1', wrong_name, 'valve2')
    assert str(err.value) == f"Component '{wrong_name}' not found in component dict."
def test_add_remove():
    old_lowest_teq = 0.2
    plumb = test.two_valve_setup(0.5, old_lowest_teq, 10, utils.CLOSED, 0.5,
                                 old_lowest_teq, 10, utils.CLOSED)

    new_lowest_teq = 0.1
    pc = test.create_component(0, 0, 0, new_lowest_teq, 'valve3', 'C')
    mapping = {1: 3, 2: 4}

    plumb.add_component(pc, mapping, 'closed', {4: (50, False)})

    assert plumb.time_res ==\
        int(utils.s_to_micros(new_lowest_teq) / utils.DEFAULT_RESOLUTION_SCALE)

    plumb.remove_component('valve3')

    assert plumb.is_valid()
    assert plumb.time_res ==\
        int(utils.s_to_micros(old_lowest_teq) / utils.DEFAULT_RESOLUTION_SCALE)
    assert plumb.edges() == [
        (1, 2, 'valve1.A1', {
            'FC': utils.teq_to_FC(utils.s_to_micros(10))
        }),
        (2, 1, 'valve1.A2', {
            'FC': 0
        }),
        (2, 3, 'valve2.B1', {
            'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
        }),
        (3, 2, 'valve2.B2', {
            'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
        }),
    ]
    assert plumb.nodes() == [
        (1, {
            'body': top.GenericNode(0)
        }),
        (2, {
            'body': top.GenericNode(0)
        }),
        (3, {
            'body': top.GenericNode(100)
        }),
    ]
    assert plumb.current_state('valve1') == 'closed'
    assert plumb.current_state('valve2') == 'open'
def test_toggle_listing():
    plumb = test.two_valve_setup(0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10,
                                 utils.CLOSED)

    pc_states = {'open': {(1, 2, 'A1'): 0, (2, 1, 'A2'): 0}}
    pc_edges = [(1, 2, 'A1'), (2, 1, 'A2')]

    pc = top.PlumbingComponent('tank', pc_states, pc_edges)

    mapping = {1: 3, 2: 4}
    plumb.add_component(pc, mapping, 'open')

    toggles = plumb.list_toggles()

    assert len(toggles) == 2
    assert 'valve1' in toggles
    assert 'valve2' in toggles
    assert 'tank' not in toggles
def test_current_pressures():
    plumb = test.two_valve_setup(
        0.5, 0.2, 10, utils.CLOSED, 0.5, 0.2, 10, utils.CLOSED)

    plumb.set_pressure(2, 50)
    plumb.set_pressure(1, 100)

    assert plumb.current_pressures() == {
        1: 100,
        2: 50,
        3: 100
    }

    assert plumb.current_pressures(1, 2) == {
        1: 100,
        2: 50
    }

    nodes = [1, 2]
    assert plumb.current_pressures(nodes) == {
        1: 100,
        2: 50
    }

    tuple_nodes = (1, 2)
    assert plumb.current_pressures(tuple_nodes) == {
        1: 100,
        2: 50
    }

    # I don't know why you'd ever do this but if you want to you can
    assert plumb.current_pressures([1], 2) == {
        1: 100,
        2: 50
    }

    assert plumb.current_pressures(3) == 100

    wrong_node = 4
    with pytest.raises(exceptions.BadInputError) as err:
        plumb.current_pressures(wrong_node)
    assert str(err.value) == f"Node {wrong_node} not found in graph."
def test_set_teq():
    old_lowest_teq = 0.2
    plumb = test.two_valve_setup(0.5, old_lowest_teq, 10, utils.CLOSED, 0.5,
                                 old_lowest_teq, 10, utils.CLOSED)

    new_lowest_teq = 0.1
    which_edge = {
        'closed': {
            (2, 1, 'A2'): new_lowest_teq,
            (1, 2, 'A1'): 7
        },
        'open': {
            (1, 2, 'A1'): 1
        }
    }

    plumb.set_teq('valve1', which_edge)

    assert plumb.time_res ==\
        int(utils.s_to_micros(new_lowest_teq) / utils.DEFAULT_RESOLUTION_SCALE)
    assert plumb.edges() == [
        (1, 2, 'valve1.A1', {
            'FC': utils.teq_to_FC(utils.s_to_micros(7))
        }),
        (2, 1, 'valve1.A2', {
            'FC': utils.teq_to_FC(utils.s_to_micros(new_lowest_teq))
        }), (2, 3, 'valve2.B1', {
            'FC': utils.teq_to_FC(utils.s_to_micros(0.5))
        }), (3, 2, 'valve2.B2', {
            'FC': utils.teq_to_FC(utils.s_to_micros(0.2))
        })
    ]
    assert plumb.component_dict['valve1'].states == {
        'open': {
            (1, 2, 'A1'): utils.teq_to_FC(utils.s_to_micros(1)),
            (2, 1, 'A2'): utils.teq_to_FC(utils.s_to_micros(old_lowest_teq))
        },
        'closed': {
            (1, 2, 'A1'): utils.teq_to_FC(utils.s_to_micros(7)),
            (2, 1, 'A2'): utils.teq_to_FC(utils.s_to_micros(new_lowest_teq))
        }
    }