Skip to content

Commit

Permalink
all tests working
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Jul 14, 2023
1 parent f34b4d6 commit 995783b
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 65 deletions.
8 changes: 4 additions & 4 deletions src/ibek/ioc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@

class Entity(BaseSettings):
"""
A baseclass for all generated Entity classes. Provides the
deserialize entry point.
A baseclass for all generated Entity classes.
"""

type: str = Field(description="The type of this entity")
Expand All @@ -39,6 +38,8 @@ def add_ibek_attributes(cls, entity: Entity):
for arg, value in entity_dict.items():
if arg in ids:
# add this entity to the global id index
if value in id_to_entity:
raise ValueError(f"Duplicate id {value} in {list(id_to_entity)}")
id_to_entity[value] = entity
elif isinstance(value, str):
# Jinja expansion of any of the Entity's string args/values
Expand Down Expand Up @@ -75,7 +76,7 @@ def lookup_instance(cls, id):
try:
return id_to_entity[id]
except KeyError:
raise KeyError(f"object id {id} not in {list(id_to_entity)}")
raise KeyError(f"object {id} not found in {list(id_to_entity)}")

validators[full_arg_name] = lookup_instance
arg_type = object
Expand Down Expand Up @@ -148,7 +149,6 @@ class NewIOC(IOC):

def clear_entity_model_ids():
"""Resets the global id_to_entity dict."""
global id_to_entity

id_to_entity.clear()

Expand Down
12 changes: 12 additions & 0 deletions tests/samples/generate_samples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ echo making values_test IOC
ibek build-startup ${SAMPLES_DIR}/values_test/values.ibek.ioc.yaml ${DEFS}/*/*.support.yaml --out /tmp/ioc/st.cmd --db-out /tmp/ioc/make_db.sh
cp /tmp/ioc/st.cmd ${SAMPLES_DIR}/values_test

PYDANTIC_DIR=${SAMPLES_DIR}/pydantic
cd $PYDANTIC_DIR

echo making the support yaml schema
ibek ibek-schema ${PYDANTIC_DIR}/../schemas/ibek.defs.schema.json

echo making the pydantic test definition schema
ibek ioc-schema ${PYDANTIC_DIR}/test.ibek.support.yaml $PYDANTIC_DIR/test.ibek.ioc.schema.json

echo making the pydantic test ioc startup script
ibek build-startup ${PYDANTIC_DIR}/test.ibek.ioc.yaml ${PYDANTIC_DIR}/test.ibek.support.yaml --out $PYDANTIC_DIR/st.cmd --db-out $PYDANTIC_DIR/make_db.sh




23 changes: 0 additions & 23 deletions tests/samples/pydantic/generate_samples.sh

This file was deleted.

14 changes: 8 additions & 6 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,12 @@ def test_build_startup_env_vars_and_post_ioc_init(

def test_loading_module_twice(tmp_path: Path, samples: Path, ibek_defs: Path):
"""
Now that we use pydantic it is OK to create the same entity twice
Verify this.
Verify we get a sensible error if we try to load a module twice
without clearing the entity model ids
"""

clear_entity_model_ids()

definition_file = samples / "pydantic" / "test.ibek.support.yaml"
instance_file = samples / "pydantic" / "test.ibek.ioc.yaml"

Expand All @@ -221,10 +222,11 @@ def test_loading_module_twice(tmp_path: Path, samples: Path, ibek_defs: Path):
generic_ioc2 = make_ioc_model(entities2)

instance = YAML(typ="safe").load(instance_file)
ioc1 = generic_ioc1(**instance)
ioc2 = generic_ioc2(**instance)
generic_ioc1(**instance)
with pytest.raises(ValueError) as ctx:
generic_ioc2(**instance)

assert ioc1.model_dump() == ioc2.model_dump()
assert "Duplicate id" in str(ctx.value)


def test_bad_counter(tmp_path: Path, samples: Path):
Expand Down
83 changes: 51 additions & 32 deletions tests/test_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
Entity classes
"""
from typing import Literal
from unittest.mock import Mock

from ibek.ioc import IOC
from ibek.ioc import clear_entity_model_ids, make_ioc_model
from ibek.render import Render


Expand Down Expand Up @@ -35,12 +34,13 @@ def test_pmac_asyn_ip_port_script(pmac_classes):


def test_geobrick_script(pmac_classes):
generated_class = find_entity_class(pmac_classes, "pmac.Geobrick")
ip_port = Mock()
ip_port.name = "my_asyn_port"
pmac_geobrick_instance = generated_class(
pmac_class = find_entity_class(pmac_classes, "pmac.Geobrick")
ip_port_class = find_entity_class(pmac_classes, "pmac.PmacAsynIPPort")

ip_port_class(name="my_asyn_port", IP="1.1")
pmac_geobrick_instance = pmac_class(
name="test_geobrick",
PORT=ip_port,
PORT="my_asyn_port",
P="geobrick_one",
numAxes=8,
idlePoll=200,
Expand All @@ -63,7 +63,9 @@ def test_geobrick_script(pmac_classes):

def test_geobrick_database(pmac_classes):
generated_class = find_entity_class(pmac_classes, "pmac.Geobrick")
ip_port_class = find_entity_class(pmac_classes, "pmac.PmacAsynIPPort")

ip_port_class(name="my_asyn_port", IP="1.1")
pmac_geobrick_instance = generated_class(
name="test_geobrick",
PORT="my_asyn_port",
Expand Down Expand Up @@ -98,8 +100,9 @@ def test_epics_environment_variables(epics_classes):

# Using the generic entity
env_name = "EPICS_CA_SERVER_PORT"
env_value = 6000
generated_class = epics_classes.EpicsEnvSet
env_value = "6000"
generated_class = find_entity_class(epics_classes, "epics.EpicsEnvSet")

epics_env_set_instance = generated_class(name=env_name, value=env_value)

env_text = render.render_environment_variables(epics_env_set_instance)
Expand All @@ -111,40 +114,51 @@ def test_entity_disabled_does_not_render_elements(pmac_classes, epics_classes):
# There are four elements to check: script, database, environment variables
# and post-iocInit

clear_entity_model_ids()

# Entity which has a script and database
pmac_geobrick_class = find_entity_class(pmac_classes, "pmac.Geobrick")
# Entity which has env_vars
ca_max_array_bytes_class = epics_classes.EpicsCaMaxArrayBytes
ca_max_array_bytes_class = find_entity_class(
epics_classes, "epics.EpicsCaMaxArrayBytes"
)
# Entity which has post_ioc_init
dbpf_class = epics_classes.Dbpf

dbpf_class = find_entity_class(epics_classes, "epics.Dbpf")
# We require pmac asyn IP port instances for the Geobrick class
pmac_asyn_ip_class = pmac_classes.PmacAsynIPPort
brick_one_asyn_ip_port = pmac_asyn_ip_class(
name="geobrick_one_port", IP="172.23.100.101"
)
brick_two_asyn_ip_port = pmac_asyn_ip_class(
name="geobrick_two_port", IP="172.23.100.101"
pmac_asyn_ip_class = find_entity_class(pmac_classes, "pmac.PmacAsynIPPort")

# Make an IOC model with our entity classes
Ioc = make_ioc_model(
[pmac_geobrick_class, ca_max_array_bytes_class, dbpf_class, pmac_asyn_ip_class]
)

# Store created instances in a list
# build a list of dictionaries to instantiate an IOC
instance_list = []

instance_list.append(
dict(type="pmac.PmacAsynIPPort", name="geobrick_one_port", IP="172.23.100.101")
)
instance_list.append(
dict(type="pmac.PmacAsynIPPort", name="geobrick_two_port", IP="172.23.100.101")
)

# Create two instances of the Geobrick entity, one disabled
instance_list.append(
pmac_geobrick_class(
dict(
type="pmac.Geobrick",
name="geobrick_enabled",
PORT=brick_one_asyn_ip_port,
PORT="geobrick_one_port",
P="geobrick_one",
numAxes=8,
idlePoll=200,
movingPoll=800,
)
)
instance_list.append(
pmac_geobrick_class(
dict(
type="pmac.Geobrick",
name="geobrick_disabled",
PORT=brick_two_asyn_ip_port,
PORT="geobrick_two_port",
P="geobrick_two",
numAxes=8,
idlePoll=200,
Expand All @@ -154,26 +168,31 @@ def test_entity_disabled_does_not_render_elements(pmac_classes, epics_classes):
)

# Create two instances of the CA max array bytes entity, one disabled
instance_list.append(ca_max_array_bytes_class())
instance_list.append(ca_max_array_bytes_class(entity_enabled=False))
instance_list.append(dict(type="epics.EpicsCaMaxArrayBytes"))
instance_list.append(dict(type="epics.EpicsCaMaxArrayBytes", entity_enabled=False))

# Create two instances of the dpbf class
instance_list.append(dbpf_class(pv="TEST:PV:1", value="pv_value_1"))
instance_list.append(dict(type="epics.Dbpf", pv="TEST:PV:1", value="pv_value_1"))
instance_list.append(
dbpf_class(pv="TEST:PV:2", value="pv_value_2", entity_enabled=False)
dict(
type="epics.Dbpf", pv="TEST:PV:2", value="pv_value_2", entity_enabled=False
)
)

# Make an IOC with our instances
ioc = IOC(
"TEST-IOC-01",
"Test IOC",
instance_list,
"test_ioc_image",
ioc = Ioc(
ioc_name="TEST-IOC-01",
description="Test IOC",
entities=instance_list,
generic_ioc_image="test_ioc_image",
)

# Render script and check output
# ControlerPort, LowLevelDriverPort, Address, Axes, MovingPoll, IdlePoll
expected_script = (
"\n# pmacAsynIPConfigure AsynPortName IPAddress\n"
"pmacAsynIPConfigure geobrick_one_port 172.23.100.101:1025\n"
"pmacAsynIPConfigure geobrick_two_port 172.23.100.101:1025\n"
"\n# pmacCreateController AsynPortName PmacAsynPort Address NumAxes "
"MovingPollPeriod IdlePollPeriod\n"
"pmacCreateController geobrick_enabled geobrick_one_port 0 8 800 200\n"
Expand Down

0 comments on commit 995783b

Please sign in to comment.