コード例 #1
0
    def setUp(self):
        # Find the schema directory
        dir = os.path.join(".")
        while SCHEMA_FOLDER not in os.listdir(dir):
            dir = os.path.join(dir, "..")

        self.fileIO = MockSynopticFileIO()
        self.bs = MockBlockServer()
        self.sm = SynopticManager(self.bs, os.path.join(dir, SCHEMA_FOLDER), MockVersionControl(), None, self.fileIO)
 def setUp(self):
     self.bs = MockBlockServer()
     self.file_manager = MockConfigurationFileManager()
     self.clm = ConfigListManager(self.bs, SCHEMA_PATH, MockVersionControl(), self.file_manager)
class TestInactiveConfigsSequence(unittest.TestCase):

    def setUp(self):
        self.bs = MockBlockServer()
        self.file_manager = MockConfigurationFileManager()
        self.clm = ConfigListManager(self.bs, SCHEMA_PATH, MockVersionControl(), self.file_manager)

    def tearDown(self):
        pass

    # Helper methods
    def _create_inactive_config_holder(self):
        configserver = InactiveConfigHolder(MACROS, MockVersionControl(), self.file_manager)
        return configserver

    def _does_pv_exist(self, name):
        fullname = self._correct_pv_name(name)
        return self.bs.does_pv_exist(fullname)

    def _correct_pv_name(self, name):
        return BlockserverPVNames.prepend_blockserver(name)

    def _create_configs(self, names):
        configserver = self._create_inactive_config_holder()
        for name in names:
            conf = create_dummy_config(name)
            configserver.set_config(conf)
            configserver.save_inactive(name)
            self.clm.update_a_config_in_list(configserver)

    def _create_components(self, names):
        configserver = self._create_inactive_config_holder()
        for name in names:
            conf = create_dummy_component(name)
            configserver.set_config(conf, True)
            configserver.save_inactive(name, True)
            self.clm.update_a_config_in_list(configserver, True)

    def _create_pvs(self, pv_names, suffix=""):
        pvs = list()
        for name in pv_names:
            pvs.append(create_pv_name(name, pvs, "DEFAULT"))

        pvs = [pv + suffix for pv in pvs]
        return pvs

    def _check_no_configs_deleted(self, is_component=False):
        if is_component:
            config_names = [c["name"] for c in self.clm.get_components()]
            self.assertEqual(len(config_names), 3)
            self.assertTrue("TEST_COMPONENT1" in config_names)
            self.assertTrue("TEST_COMPONENT2" in config_names)
            self.assertTrue("TEST_COMPONENT3" in config_names)
        else:
            config_names = [c["name"] for c in self.clm.get_configs()]
            self.assertEqual(len(config_names), 3)
            self.assertTrue("TEST_CONFIG2" in config_names)
            self.assertTrue("TEST_CONFIG1" in config_names)
            self.assertTrue("TEST_ACTIVE" in config_names)

    def _check_pv_changed_but_not_name(self, config_name, expected_pv_name):
        self._create_configs([config_name])
        confs = self.clm.get_configs()

        self.assertEqual(len(confs), 1)
        self.assertEqual(confs[0]["pv"], expected_pv_name)
        self.assertEqual(confs[0]["name"], config_name)

        self.assertTrue(self._does_pv_exist(expected_pv_name + GET_CONFIG_PV))
        self.assertFalse(self._does_pv_exist(config_name + GET_CONFIG_PV))

    # Tests
    def test_initialisation_with_no_configs(self):
        confs = self.clm.get_configs()
        self.assertEqual(len(confs), 0)
        comps = self.clm.get_components()
        self.assertEqual(len(comps), 0)

    def test_initialisation_with_configs(self):
        self._create_configs(["TEST_CONFIG1", "TEST_CONFIG2"])
        confs = self.clm.get_configs()
        self.assertEqual(len(confs), 2)
        self.assertTrue("TEST_CONFIG1" in [c["name"] for c in confs])
        self.assertTrue("TEST_CONFIG2" in [c["name"] for c in confs])

    def test_initialisation_with_components(self):
        self._create_components(["TEST_COMPONENT1", "TEST_COMPONENT2"])
        confs = self.clm.get_components()
        self.assertEqual(len(confs), 2)
        self.assertTrue("TEST_COMPONENT1" in [c["name"] for c in confs])
        self.assertTrue("TEST_COMPONENT2" in [c["name"] for c in confs])

    def test_initialisation_with_configs_creates_pvs(self):
        self._create_configs(["TEST_CONFIG1", "TEST_CONFIG2"])

        pvs = self._create_pvs(["TEST_CONFIG1", "TEST_CONFIG2"], GET_CONFIG_PV)
        pvs += self._create_pvs(["TEST_CONFIG1", "TEST_CONFIG2"], GET_COMPONENT_PV)

        for pv in pvs[:2]:
            self.assertTrue(self._does_pv_exist(pv))
        for pv in pvs[2:]:
            self.assertFalse(self._does_pv_exist(pv))

    def test_initialisation_with_components_creates_pv(self):
        comps = ["TEST_COMPONENT1", "TEST_COMPONENT2"]
        self._create_components(comps)

        pvs = self._create_pvs(comps, GET_COMPONENT_PV)
        pvs += self._create_pvs(comps, DEPENDENCIES_PV)
        pvs += self._create_pvs(comps, GET_CONFIG_PV)

        for pv in pvs[:4]:
            self.assertTrue(self._does_pv_exist(pv))
        for pv in pvs[4:]:
            self.assertFalse(self._does_pv_exist(pv))

    def test_update_config_from_object(self):
        self.icm = self._create_inactive_config_holder()
        self.icm.set_config_details(VALID_CONFIG)
        self.clm.update_a_config_in_list(self.icm)

        confs = self.clm.get_configs()
        self.assertEqual(len(confs), 1)
        self.assertTrue("TEST_CONFIG" in [conf.get('name') for conf in confs])
        self.assertTrue(create_pv_name("TEST_CONFIG", [], "") in [conf.get('pv') for conf in confs])
        self.assertTrue("A Test Configuration" in [conf.get('description') for conf in confs])
        self.assertTrue("TEST_SYNOPTIC" in [conf.get('synoptic') for conf in confs])

        comps = self.clm.get_components()
        self.assertEqual(len(comps), 0)

    def test_add_a_new_component_to_list(self):
        self.icm = self._create_inactive_config_holder()
        self.icm.set_config_details(VALID_CONFIG)
        self.clm.update_a_config_in_list(self.icm, True)

        confs = self.clm.get_components()
        self.assertEqual(len(confs), 1)
        self.assertTrue("TEST_CONFIG" in [conf.get('name') for conf in confs])
        self.assertTrue(create_pv_name("TEST_CONFIG", [], "") in [conf.get('pv') for conf in confs])
        self.assertTrue("A Test Configuration" in [conf.get('description') for conf in confs])
        self.assertTrue("TEST_SYNOPTIC" in [conf.get('synoptic') for conf in confs])

        comps = self.clm.get_configs()
        self.assertEqual(len(comps), 0)

    def test_add_multiple_components(self):
        self._create_components(["TEST_COMPONENT1", "TEST_COMPONENT2"])
        comps = self.clm.get_components()
        for comp in comps:
            self.assertEqual(len(comp), 5)
            self.assertTrue("name" in comp)
            self.assertTrue("pv" in comp)
            self.assertTrue("description" in comp)
            self.assertTrue("synoptic" in comp)
            self.assertTrue("history" in comp)
        self.assertTrue("TEST_COMPONENT1" in [comp.get('name') for comp in comps])
        self.assertTrue("TEST_COMPONENT2" in [comp.get('name') for comp in comps])

    def test_pv_of_lower_case_name(self):
        config_name = "test_CONfig1"
        self._check_pv_changed_but_not_name(config_name, create_pv_name(config_name, [], ""))

    def test_config_and_component_allowed_same_pv(self):
        self._create_configs(["TEST_CONFIG_AND_COMPONENT1", "TEST_CONFIG_AND_COMPONENT2"])
        self._create_components(["TEST_CONFIG_AND_COMPONENT1", "TEST_CONFIG_AND_COMPONENT2"])

        confs = self.clm.get_configs()
        self.assertEqual(len(confs), 2)

        pvs = self._create_pvs(["TEST_CONFIG_AND_COMPONENT1", "TEST_CONFIG_AND_COMPONENT2"], "")

        self.assertTrue(pvs[0] in [m["pv"] for m in confs])
        self.assertTrue(pvs[1] in [m["pv"] for m in confs])

        comps = self.clm.get_components()
        self.assertEqual(len(comps), 2)

        self.assertTrue(pvs[0] in [m["pv"] for m in comps])
        self.assertTrue(pvs[1] in [m["pv"] for m in comps])

    def test_delete_configs_with_empty_list_does_nothing(self):
        self._create_configs(["TEST_CONFIG1", "TEST_CONFIG2"])

        self.clm.active_config_name = "TEST_ACTIVE"
        self.clm.delete([])

        config_names = [c["name"] for c in self.clm.get_configs()]
        self.assertEqual(len(config_names), 2)
        self.assertTrue("TEST_CONFIG1" in config_names)
        self.assertTrue("TEST_CONFIG2" in config_names)

    def test_delete_components_with_empty_list_does_nothing(self):
        comp_names = ["TEST_COMPONENT1", "TEST_COMPONENT2"]
        self._create_components(comp_names)

        self.clm.active_config_name = "TEST_ACTIVE"
        self.clm.delete([], True)

        config_names = [c["name"] for c in self.clm.get_components()]
        self.assertEqual(len(config_names), 2)
        self.assertTrue(comp_names[0] in config_names)
        self.assertTrue(comp_names[1] in config_names)

        pvs = self._create_pvs(comp_names, GET_COMPONENT_PV)
        pvs += self._create_pvs(comp_names, DEPENDENCIES_PV)

        for pv in pvs:
            self.assertTrue(self._does_pv_exist(pv))

    def test_delete_active_config_throws(self):
        self._create_configs(["TEST_CONFIG1", "TEST_CONFIG2"])
        active = ActiveConfigHolder(MACROS, ArchiverManager(None, None, MockArchiverWrapper()),
                                    MockVersionControl(), self.file_manager, MockIocControl(""))
        active.save_active("TEST_ACTIVE")
        self.clm.update_a_config_in_list(active)
        self.clm.active_config_name = "TEST_ACTIVE"

        self._check_no_configs_deleted()
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_ACTIVE"])
        self._check_no_configs_deleted()
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_ACTIVE", "TEST_CONFIG1"])
        self._check_no_configs_deleted()
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_CONFIG1", "TEST_ACTIVE"])
        self._check_no_configs_deleted()

    def test_delete_active_component_throws(self):
        self._create_components(["TEST_COMPONENT1", "TEST_COMPONENT2", "TEST_COMPONENT3"])
        active = ActiveConfigHolder(MACROS, ArchiverManager(None, None, MockArchiverWrapper()),
                                    MockVersionControl(), self.file_manager, MockIocControl(""))
        active.add_component("TEST_COMPONENT1", Configuration(MACROS))
        active.save_active("TEST_ACTIVE")
        self.clm.active_config_name = "TEST_ACTIVE"

        self.clm.update_a_config_in_list(active)

        self._check_no_configs_deleted(True)
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_COMPONENT1"], True)
        self._check_no_configs_deleted(True)
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_COMPONENT1", "TEST_COMPONENT2"], True)
        self._check_no_configs_deleted(True)
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_CONFIG2", "TEST_COMPONENT1"], True)
        self._check_no_configs_deleted(True)

    def test_delete_used_component_throws(self):
        self._create_components(["TEST_COMPONENT3", "TEST_COMPONENT2", "TEST_COMPONENT1"])

        inactive = self._create_inactive_config_holder()
        inactive.add_component("TEST_COMPONENT1", Configuration(MACROS))
        inactive.save_inactive("TEST_INACTIVE")

        self.clm.update_a_config_in_list(inactive)
        self.clm.active_config_name = "TEST_ACTIVE"

        self._check_no_configs_deleted(True)
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_COMPONENT1"], True)
        self._check_no_configs_deleted(True)
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_COMPONENT1", "TEST_COMPONENT2"], True)
        self._check_no_configs_deleted(True)
        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_CONFIG2", "TEST_COMPONENT1"], True)
        self._check_no_configs_deleted(True)

    def test_delete_one_inactive_config_works(self):
        self._create_configs(["TEST_CONFIG1", "TEST_CONFIG2"])

        self.clm.delete(["TEST_CONFIG1"])
        self.clm.active_config_name = "TEST_ACTIVE"

        config_names = [c["name"] for c in self.clm.get_configs()]
        self.assertEqual(len(config_names), 1)
        self.assertTrue("TEST_CONFIG2" in config_names)
        self.assertFalse("TEST_CONFIG1" in config_names)

    def test_delete_one_inactive_component_works(self):
        comps = ["TEST_COMPONENT1", "TEST_COMPONENT2"]
        self._create_components(comps)

        self.clm.delete(["TEST_COMPONENT1"], True)
        self.clm.active_config_name = "TEST_ACTIVE"

        config_names = [c["name"] for c in self.clm.get_components()]
        self.assertEqual(len(config_names), 1)
        self.assertTrue("TEST_COMPONENT2" in config_names)
        self.assertFalse("TEST_COMPONENT1" in config_names)

        pvs = self._create_pvs(comps, GET_COMPONENT_PV)
        pvs += self._create_pvs(comps, DEPENDENCIES_PV)
        self.assertFalse(self._does_pv_exist(pvs[0]))
        self.assertTrue(self._does_pv_exist(pvs[1]))
        self.assertFalse(self._does_pv_exist(pvs[2]))
        self.assertTrue(self._does_pv_exist(pvs[3]))

    def test_delete_many_inactive_configs_works(self):
        self._create_configs(["TEST_CONFIG1", "TEST_CONFIG2", "TEST_CONFIG3"])
        self.clm.active_config_name = "TEST_ACTIVE"

        config_names = [c["name"] for c in self.clm.get_configs()]
        self.assertEqual(len(config_names), 3)
        self.assertTrue("TEST_CONFIG1" in config_names)
        self.assertTrue("TEST_CONFIG2" in config_names)
        self.assertTrue("TEST_CONFIG3" in config_names)

        self.clm.delete(["TEST_CONFIG1", "TEST_CONFIG3"])
        config_names = [c["name"] for c in self.clm.get_configs()]

        self.assertEqual(len(config_names), 1)
        self.assertTrue("TEST_CONFIG2" in config_names)
        self.assertFalse("TEST_CONFIG1" in config_names)
        self.assertFalse("TEST_CONFIG3" in config_names)

    def test_delete_many_inactive_components_works(self):
        all_comp_names = ["TEST_COMPONENT1", "TEST_COMPONENT2", "TEST_COMPONENT3"]
        self._create_components(all_comp_names)
        self.clm.active_config_name = "TEST_ACTIVE"

        config_names = [c["name"] for c in self.clm.get_components()]
        self.assertEqual(len(config_names), 3)
        self.assertTrue("TEST_COMPONENT1" in config_names)
        self.assertTrue("TEST_COMPONENT2" in config_names)
        self.assertTrue("TEST_COMPONENT3" in config_names)

        self.clm.delete(["TEST_COMPONENT2", "TEST_COMPONENT3"], True)

        config_names = [c["name"] for c in self.clm.get_components()]
        self.assertEqual(len(config_names), 1)
        self.assertTrue("TEST_COMPONENT1" in config_names)
        self.assertFalse("TEST_COMPONENT2" in config_names)
        self.assertFalse("TEST_COMPONENT3" in config_names)

        pvs = self._create_pvs(all_comp_names, GET_COMPONENT_PV)
        pvs += self._create_pvs(all_comp_names, DEPENDENCIES_PV)

        self.assertTrue(self._does_pv_exist(pvs[0]))
        self.assertTrue(self._does_pv_exist(pvs[3]))
        self.assertFalse(self._does_pv_exist(pvs[1]))
        self.assertFalse(self._does_pv_exist(pvs[2]))
        for pv in pvs[4:]:
            self.assertFalse(self._does_pv_exist(pv))

    def test_cant_delete_non_existent_config(self):
        self.clm.active_config_name = "TEST_ACTIVE"

        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_CONFIG1"])

        config_names = [c["name"] for c in self.clm.get_configs()]
        self.assertEqual(len(config_names), 0)

    def test_cant_delete_non_existent_component(self):
        self.clm.active_config_name = "TEST_ACTIVE"

        self.assertRaises(InvalidDeleteException, self.clm.delete, ["TEST_COMPONENT1"], True)

        config_names = [c["name"] for c in self.clm.get_components()]
        self.assertEqual(len(config_names), 0)

    def test_required_pvs_are_created(self):
        comp_names = ["TEST_COMPONENT1"]
        self._create_components(comp_names)

        pvs = self._create_pvs(comp_names, GET_COMPONENT_PV)
        pvs += self._create_pvs(comp_names, DEPENDENCIES_PV)

        for pv in pvs:
            self.assertTrue(self._does_pv_exist(pv))

    def test_required_pvs_are_deleted_when_component_deleted(self):
        comp_names = ["TEST_COMPONENT1"]
        self._create_components(comp_names)
        pvs = self._create_pvs(comp_names, GET_COMPONENT_PV)
        pvs += self._create_pvs(comp_names, DEPENDENCIES_PV)

        for pv in pvs:
            self.assertTrue(self._does_pv_exist(pv))

        self.clm.delete(comp_names, True)

        for pv in pvs:
            self.assertFalse(self._does_pv_exist(pv))

    def test_dependencies_updates_when_component_added_to_config(self):
        self._create_components(["TEST_COMPONENT1"])
        inactive = self._create_inactive_config_holder()
        inactive.add_component("TEST_COMPONENT1", Configuration(MACROS))
        inactive.save_inactive("TEST_INACTIVE")
        self.clm.update_a_config_in_list(inactive)
        self.assertTrue("TEST_INACTIVE" in self.clm.get_dependencies("TEST_COMPONENT1"))

    def test_dependencies_updates_remove(self):
        self._create_components(["TEST_COMPONENT1"])

        inactive = self._create_inactive_config_holder()

        inactive.add_component("TEST_COMPONENT1", Configuration(MACROS))
        inactive.save_inactive("TEST_INACTIVE", False)
        self.clm.update_a_config_in_list(inactive)

        inactive.remove_comp("TEST_COMPONENT1")
        inactive.save_inactive("TEST_INACTIVE", False)
        self.clm.update_a_config_in_list(inactive)

        self.assertFalse("TEST_INACTIVE" in self.clm.get_dependencies("TEST_COMPONENT1"))

    def test_delete_config_deletes_dependency(self):
        self._create_components(["TEST_COMPONENT1"])

        inactive = self._create_inactive_config_holder()
        self.clm.active_config_name = "TEST_ACTIVE"
        inactive.add_component("TEST_COMPONENT1", Configuration(MACROS))
        inactive.save_inactive("TEST_INACTIVE", False)
        self.clm.update_a_config_in_list(inactive)
        self.clm.delete(["TEST_INACTIVE"])
        self.assertFalse("TEST_INACTIVE" in self.clm.get_dependencies("TEST_COMPONENT1"))

    def test_cannot_delete_default(self):
        self._create_components(["TEST_COMPONENT1"])

        self.assertRaises(InvalidDeleteException, self.clm.delete, [DEFAULT_COMPONENT], True)

    def test_update_inactive_config_from_filewatcher(self):
        inactive = self._create_inactive_config_holder()
        self.bs.set_config_list(self.clm)

        inactive.save_inactive("TEST_INACTIVE")
        self.clm.update(inactive)

        self.assertEqual(len(self.clm.get_components()), 0)
        self.assertEqual(len(self.clm.get_configs()), 1)
        self.assertTrue("TEST_INACTIVE" in [x['name'] for x in self.clm.get_configs()])

    def test_update_inactive_component_from_filewatcher(self):
        inactive = self._create_inactive_config_holder()
        self.bs.set_config_list(self.clm)

        inactive.save_inactive("TEST_INACTIVE_COMP", True)
        self.clm.update(inactive, True)

        self.assertEqual(len(self.clm.get_components()), 1)
        self.assertEqual(len(self.clm.get_configs()), 0)
        self.assertTrue("TEST_INACTIVE_COMP" in [x['name'] for x in self.clm.get_components()])

    def test_update_active_config_from_filewatcher(self):
        active = self._create_inactive_config_holder()
        active_config_name = "TEST_ACTIVE"

        self.bs.set_config_list(self.clm)
        self.clm.active_config_name = active_config_name

        active.save_inactive(active_config_name)
        self.clm.update(active)

        self.assertEqual(len(self.clm.get_components()), 0)
        self.assertEqual(len(self.clm.get_configs()), 1)
        self.assertTrue("TEST_ACTIVE" in [x['name'] for x in self.clm.get_configs()])

    def test_update_active_component_from_filewatcher(self):
        inactive = self._create_inactive_config_holder()
        active_config_name = "TEST_ACTIVE"
        active_config_comp = "TEST_ACTIVE_COMP"

        self.bs.set_config_list(self.clm)
        self.clm.active_config_name = active_config_name
        self.clm.active_components = [active_config_comp]

        inactive.save_inactive(active_config_comp, True)
        self.clm.update(inactive, True)

        self.assertEqual(len(self.clm.get_components()), 1)
        self.assertEqual(len(self.clm.get_configs()), 0)
        self.assertTrue("TEST_ACTIVE_COMP" in [x['name'] for x in self.clm.get_components()])

    def test_default_filtered(self):
        comps = self.clm.get_components()
        self.assertTrue(DEFAULT_COMPONENT not in comps)
コード例 #4
0
class TestSynopticManagerSequence(unittest.TestCase):
    def setUp(self):
        # Find the schema directory
        dir = os.path.join(".")
        while SCHEMA_FOLDER not in os.listdir(dir):
            dir = os.path.join(dir, "..")

        self.fileIO = MockSynopticFileIO()
        self.bs = MockBlockServer()
        self.sm = SynopticManager(self.bs, os.path.join(dir, SCHEMA_FOLDER), MockVersionControl(), None, self.fileIO)

    def tearDown(self):
        pass

    def _create_a_synoptic(self, name):
        self.sm.save_synoptic_xml(EXAMPLE_SYNOPTIC % name)

    def test_get_synoptic_names_returns_names_alphabetically(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        self._create_a_synoptic(SYNOPTIC_2)

        # Act
        s = self.sm.get_synoptic_list()

        # Assert
        self.assertTrue(len(s) > 0)
        n = [x['name'] for x in s]
        print n
        self.assertEqual("-- NONE --", n[0])
        self.assertEqual(SYNOPTIC_1, n[1])
        self.assertEqual(SYNOPTIC_2, n[2])

    def test_create_pvs_is_okay(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        # Act
        self.sm._load_initial()

        # Assert
        self.assertTrue(self.bs.does_pv_exist("%sSYNOP1%s" % (SYNOPTIC_PRE, SYNOPTIC_GET)))

    def test_get_default_synoptic_xml_returns_nothing(self):
        # Arrange
        # Act
        xml = self.sm.get_default_synoptic_xml()

        # Assert
        self.assertEqual(xml, "")

    def test_set_default_synoptic_xml_sets_something(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        # Act
        self.sm.save_synoptic_xml(EXAMPLE_SYNOPTIC % "synoptic0")
        self.sm.set_default_synoptic("synoptic0")

        # Assert
        xml = self.sm.get_default_synoptic_xml()

        self.assertTrue(len(xml) > 0)
        # Check the correct name appears in the xml
        self.assertTrue("synoptic0" in xml)

    def test_set_current_synoptic_xml_creates_pv(self):
        # Arrange
        syn_name = "synopt"

        # Act
        self.sm.save_synoptic_xml(EXAMPLE_SYNOPTIC % syn_name)

        # Assert
        self.assertTrue(self.bs.does_pv_exist("%sSYNOPT%s" % (SYNOPTIC_PRE, SYNOPTIC_GET)))

    def test_delete_synoptics_empty(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        self._create_a_synoptic(SYNOPTIC_2)
        initial_len = len(self.sm.get_synoptic_list())
        # Act
        self.sm.delete([])

        # Assert
        synoptic_names = [c["name"] for c in self.sm.get_synoptic_list()]
        self.assertEqual(len(synoptic_names), initial_len)
        self.assertTrue(SYNOPTIC_1 in synoptic_names)
        self.assertTrue(SYNOPTIC_2 in synoptic_names)
        self.assertTrue(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_1.upper())))
        self.assertTrue(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_2.upper())))

    def test_delete_one_synoptic(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        self._create_a_synoptic(SYNOPTIC_2)
        initial_len = len(self.sm.get_synoptic_list())

        # Act
        self.sm.delete([SYNOPTIC_1])

        # Assert
        synoptic_names = [c["name"] for c in self.sm.get_synoptic_list()]
        self.assertEqual(len(synoptic_names), initial_len - 1)
        self.assertFalse(SYNOPTIC_1 in synoptic_names)
        self.assertTrue(SYNOPTIC_2 in synoptic_names)
        self.assertFalse(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_1.upper())))
        self.assertTrue(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_2.upper())))

    def test_delete_many_synoptics(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        self._create_a_synoptic(SYNOPTIC_2)
        initial_len = len(self.sm.get_synoptic_list())
        # Act
        self.sm.delete([SYNOPTIC_1, SYNOPTIC_2])

        # Assert
        synoptic_names = [c["name"] for c in self.sm.get_synoptic_list()]
        self.assertEqual(len(synoptic_names), initial_len - 2)
        self.assertFalse(SYNOPTIC_1 in synoptic_names)
        self.assertFalse(SYNOPTIC_2 in synoptic_names)
        self.assertFalse(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_1.upper())))
        self.assertFalse(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_2.upper())))

    def test_cannot_delete_non_existent_synoptic(self):
        # Arrange
        self._create_a_synoptic(SYNOPTIC_1)
        self._create_a_synoptic(SYNOPTIC_2)
        initial_len = len(self.sm.get_synoptic_list())
        # Act
        self.assertRaises(InvalidDeleteException, self.sm.delete, ["invalid"])

        # Assert
        synoptic_names = [c["name"] for c in self.sm.get_synoptic_list()]
        self.assertEqual(len(synoptic_names), initial_len)
        self.assertTrue(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_1.upper())))
        self.assertTrue(self.bs.does_pv_exist(construct_pv_name(SYNOPTIC_2.upper())))