Skip to content

Commit

Permalink
Added test for observatory_util and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Meisinger committed Dec 30, 2012
1 parent 17af4d2 commit 81f5f0e
Show file tree
Hide file tree
Showing 3 changed files with 294 additions and 30 deletions.
76 changes: 76 additions & 0 deletions ion/core/mockutil.py
@@ -0,0 +1,76 @@
#!/usr/bin/env python

__author__ = 'Michael Meisinger'

from mock import Mock, patch
from nose.plugins.attrib import attr

from pyon.ion.identifier import create_unique_resource_id, create_unique_association_id, create_unique_event_id
from pyon.public import IonObject
from pyon.util.containers import get_ion_ts

class MockUtil(object):
def __init__(self):
self.res_objs = {}
self.res_id_list = []
self.associations = []

def create_process_mock(self):
self.process_mock = Mock()
return self.process_mock

def create_container_mock(self, capabilities=None):
self.container_mock = Mock()
self.container_mock.resource_registry = Mock()

return self.container_mock

def load_mock_resources(self, res_list):
for res_entry in res_list:
name = res_entry.get('name', 'NO_NAME')
lcstate = res_entry.get('lcstate', 'DEPLOYED_AVAILABLE')
attr = res_entry.get('attr', {})
res_id = create_unique_resource_id()
res_id = res_entry.get('_id', res_id)
res_obj = IonObject(res_entry['rt'], name=name, **attr)
res_obj._id = res_id
res_obj.lcstate = lcstate
res_obj.ts_created = get_ion_ts()
res_obj.ts_updated = res_obj.ts_created

self.res_objs[res_id] = res_obj
self.res_id_list.append(res_id)

self.container_mock.resource_registry.read_mult = Mock()
def side_effect(res_id_list):
return [self.res_objs[res_id] for res_id in res_id_list]
self.container_mock.resource_registry.read_mult.side_effect = side_effect

def load_mock_associations(self, assoc_list):
for assoc_entry in assoc_list:
sid = assoc_entry[0]
oid = assoc_entry[2]
st = self.res_objs[sid]._get_type()
ot = self.res_objs[oid]._get_type()
ass_obj = IonObject('Association', s=sid, st=st, o=oid, ot=ot, p=assoc_entry[1], ts=get_ion_ts())
ass_obj._id = "%s_%s_%s" % (sid, assoc_entry[1], oid)
self.associations.append(ass_obj)

def load_mock_events(self, event_list):
for event_entry in event_list:
pass

def assign_mockres_find_associations(self, filter_predicate=None):
self.container_mock.resource_registry.find_associations = Mock()
assocs = self.associations
if filter_predicate:
assocs = [assoc for assoc in self.associations if assoc.p == filter_predicate]
self.container_mock.resource_registry.find_associations.return_value = assocs

def assign_mockres_find_objects(self, filter_predicate=None):
self.container_mock.resource_registry.find_objects = Mock()
assocs = self.associations
if filter_predicate:
assocs = [assoc for assoc in self.associations if assoc.p == filter_predicate]
res_ids = [a.o for a in assocs]
self.container_mock.resource_registry.find_objects.return_value = [res_ids, assocs]
72 changes: 42 additions & 30 deletions ion/services/sa/observatory/observatory_util.py
Expand Up @@ -23,36 +23,47 @@ def __init__(self, process=None, container=None):

def get_child_sites(self, parent_site_id=None, org_id=None, exclude_types=None, include_parents=True, id_only=True):
"""
Returns all child sites for a given parent site_id or a given org_id.
Returns all child sites and parent site for a given parent site_id.
Returns all child sites and org for a given org_id.
Return type is a tuple of two elements.
The first element is a dict mapping site_id to Site object (or None if id_only==True).
The second element is a dict mapping site_id to a list of direct child site_ids.
@param include_parents if True, walk up the parents all the way to the root and include
@param id_only if True, return Site objects
"""
if parent_site_id and org_id:
raise BadRequest("Either parent_site_id OR org_id supported!")
if exclude_types is None:
exclude_types = []

parents = self._get_site_parents() # Note: root elements are not in list

if org_id:
obsite_ids,_ = self.container.resource_registry.find_objects(
org_id, PRED.hasResource, RT.Observatory, id_only=True)
if not obsite_ids:
return {}, {}
parent_site_list = set(obsite_ids)
parent_site_id = org_id
for obsite_id in obsite_ids:
parents[obsite_id] = ('Observatory', org_id, 'Org')
elif parent_site_id:
parent_site_list = set([parent_site_id])
if parent_site_id not in parents:
parents[parent_site_id] = ('Observatory', None, 'Org')
else:
raise BadRequest("Must provide either parent_site_id or org_id")
matchlist = []
ancestors = {}
parents = self._get_site_parents()
for p_site in parent_site_list:
if org_id and p_site not in parents:
parents[p_site] = ('Observatory', org_id, 'Org')
for rid, (st, psid, pt) in parents.iteritems():

matchlist = [] # sites with wanted parent
ancestors = {} # child ids for sites in result set
for site_id, (st, parent_id, pt) in parents.iteritems():
# Iterate through sites and find the ones with a wanted parent
if st in exclude_types:
continue
parent_stack = [rid, psid]
while psid:
if psid in parent_site_list or (include_parents and rid in parent_site_list):
matchlist.append(rid)
parent_stack = [site_id, parent_id]
while parent_id:
# Walk up to parents
if parent_id == parent_site_id:
matchlist.append(site_id)
# Fill out ancestors
par = parent_stack.pop()
while parent_stack:
ch = parent_stack.pop()
Expand All @@ -61,28 +72,29 @@ def get_child_sites(self, parent_site_id=None, org_id=None, exclude_types=None,
if ch not in ancestors[par]:
ancestors[par].append(ch)
par = ch
psid = None
parent_id = None
else:
_,psid,_ = parents.get(psid, (None,None,None))
parent_stack.append(psid)
_,parent_id,_ = parents.get(parent_id, (None,None,None))
parent_stack.append(parent_id)

# Go all the way up to the roots
if include_parents:
for p_site in parent_site_list:
child_id = p_site
matchlist.append(parent_site_id)
child_id = parent_site_id
parent = parents.get(child_id, None)
while parent:
st, parent_id, pt = parent
if parent_id:
matchlist.append(parent_id)
if parent_id not in ancestors:
ancestors[parent_id] = []
ancestors[parent_id].append(child_id)
child_id = parent_id
parent = parents.get(child_id, None)
while parent:
st, psid, pt = parent
matchlist.append(psid)
if psid not in ancestors:
ancestors[psid] = []
ancestors[psid].append(child_id)
child_id = psid
parent = parents.get(child_id, None)

if id_only:
child_site_dict = dict(zip(matchlist, [None]*len(matchlist)))
else:
if org_id and include_parents:
matchlist.append(org_id)
all_res = self.container.resource_registry.read_mult(matchlist) if matchlist else []
child_site_dict = dict(zip([res._id for res in all_res], all_res))

Expand Down Expand Up @@ -133,7 +145,7 @@ def add_children(dev_id):
if dev_id not in all_children:
del child_devices[dev_id]
if device_id not in child_devices:
child_devices[device_id] = None
child_devices[device_id] = []
return child_devices

def _get_child_devices(self):
Expand Down
176 changes: 176 additions & 0 deletions ion/services/sa/observatory/test/test_observatory_util.py
@@ -0,0 +1,176 @@
#!/usr/bin/env python

__author__ = 'Michael Meisinger'

import unittest
from mock import Mock, patch
from nose.plugins.attrib import attr

from pyon.public import log, RT
from pyon.util.unit_test import PyonTestCase

from ion.core.mockutil import MockUtil
from ion.services.sa.observatory.observatory_util import ObservatoryUtil

@attr('UNIT', group='saob')
class TestObservatoryUtil(unittest.TestCase):

def setUp(self):
self.mu = MockUtil()
self.process_mock = self.mu.create_process_mock()
self.container_mock = self.mu.create_container_mock()

res_list = [
dict(rt='Org', _id='Org_1', attr={}),
dict(rt='Observatory', _id='Obs_1', attr={}),
dict(rt='Observatory', _id='Obs_2', attr={}),
dict(rt='Subsite', _id='Sub_1', attr={}),
dict(rt='Subsite', _id='Sub_2', attr={}),
dict(rt='PlatformSite', _id='PS_1', attr={}),
dict(rt='InstrumentSite', _id='IS_1', attr={}),

dict(rt='PlatformDevice', _id='PD_1', attr={}),
dict(rt='InstrumentDevice', _id='ID_1',attr={}),
]

assoc_list = [
['Obs_1', 'hasSite', 'Sub_1'],
['Sub_1', 'hasSite', 'PS_1'],
['PS_1', 'hasSite', 'IS_1'],
]
assoc_list1 = [
['Org_1', 'hasResource', 'Obs_1'],
['Org_1', 'hasResource', 'Obs_2'],
['Obs_2', 'hasSite', 'Sub_2'],
]
assoc_list2 = [
['PS_1', 'hasDevice', 'PD_1'],
['IS_1', 'hasDevice', 'ID_1'],

['PD_1', 'hasDevice', 'ID_1'],
]

event_list = [
dict(et='EventType', o='origin', ot='origin_type', st='sub_type', att={})
]


def test_get_child_sites(self):
self.mu.load_mock_resources(self.res_list)
self.mu.load_mock_associations(self.assoc_list)

self.mu.assign_mockres_find_associations(filter_predicate="hasSite")

self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='Obs_1', include_parents=False, id_only=True)
self.assertEquals(len(child_sites), 3)
self.assertEquals(len(site_ancestors), 3)
self.assertIn('Sub_1', child_sites)
self.assertIn('PS_1', child_sites)
self.assertIn('IS_1', child_sites)
self.assertNotIn('Obs_1', child_sites)
self.assertEquals(len([v for v in child_sites.values() if v is None]), 3)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='Obs_1', include_parents=False, id_only=False)
self.assertEquals(len(child_sites), 3)
self.assertEquals(len(site_ancestors), 3)
self.assertEquals(len([v for v in child_sites.values() if v is None]), 0)
self.assertEquals(child_sites['Sub_1']._get_type(), RT.Subsite)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='Obs_1', include_parents=True)
self.assertEquals(len(child_sites), 4)
self.assertEquals(len(site_ancestors), 3)
self.assertIn('Obs_1', child_sites)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='Sub_1', include_parents=False)
self.assertEquals(len(child_sites), 2)
self.assertEquals(len(site_ancestors), 2)
self.assertNotIn('Sub_1', child_sites)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='Sub_1', include_parents=True)
self.assertEquals(len(child_sites), 4)
self.assertEquals(len(site_ancestors), 3)
self.assertIn('Sub_1', child_sites)
self.assertIn('Obs_1', child_sites)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='PS_1', include_parents=False)
self.assertEquals(len(child_sites), 1)
self.assertEquals(len(site_ancestors), 1)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='PS_1', include_parents=True)
self.assertEquals(len(child_sites), 4)
self.assertEquals(len(site_ancestors), 3)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='IS_1', include_parents=False)
self.assertEquals(len(child_sites), 0)
self.assertEquals(len(site_ancestors), 0)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='IS_1', include_parents=True)
self.assertEquals(len(child_sites), 4)
self.assertEquals(len(site_ancestors), 3)

child_sites, site_ancestors = self.obs_util.get_child_sites(parent_site_id='XXX', include_parents=True)
self.assertEquals(len(child_sites), 1)
self.assertEquals(len(site_ancestors), 0)

def test_get_child_sites_org(self):
self.mu.load_mock_resources(self.res_list)
self.mu.load_mock_associations(self.assoc_list + self.assoc_list1)

self.mu.assign_mockres_find_associations(filter_predicate="hasSite")
self.mu.assign_mockres_find_objects(filter_predicate="hasResource")

self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)

child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=False, id_only=True)
self.assertEquals(len(child_sites), 6)
self.assertEquals(len(site_ancestors), 5)
self.assertIn('Sub_1', child_sites)
self.assertIn('PS_1', child_sites)
self.assertIn('IS_1', child_sites)
self.assertIn('Obs_1', child_sites)
self.assertIn('Obs_2', child_sites)

child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=True, id_only=True)
self.assertEquals(len(child_sites), 7)
self.assertEquals(len(site_ancestors), 5)

child_sites, site_ancestors = self.obs_util.get_child_sites(org_id='Org_1', include_parents=True, id_only=False)
self.assertEquals(len(child_sites), 7)
self.assertEquals(len(site_ancestors), 5)
self.assertEquals(len([v for v in child_sites.values() if v is None]), 0)
self.assertEquals(child_sites['Org_1']._get_type(), RT.Org)

def test_get_site_devices(self):
self.mu.load_mock_resources(self.res_list)
self.mu.load_mock_associations(self.assoc_list2)

self.mu.assign_mockres_find_associations(filter_predicate="hasDevice")

self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
site_devices = self.obs_util.get_site_devices(['Sub_1', 'PS_1', 'IS_1'])
self.assertEquals(len(site_devices), 3)
self.assertEquals(site_devices['Sub_1'], None)
self.assertEquals(site_devices['IS_1'], ('InstrumentSite', 'ID_1', 'InstrumentDevice'))

def test_get_child_devices(self):
self.mu.load_mock_resources(self.res_list)
self.mu.load_mock_associations(self.assoc_list2)
self.mu.assign_mockres_find_associations(filter_predicate="hasDevice")

self.obs_util = ObservatoryUtil(self.process_mock, self.container_mock)
child_devices = self.obs_util.get_child_devices('PD_1')
self.assertEquals(len(child_devices), 1)
self.assertEquals(child_devices['PD_1'][0][1], 'ID_1')

child_devices = self.obs_util.get_child_devices('ID_1')
self.assertEquals(len(child_devices), 1)
self.assertEquals(child_devices['ID_1'], [])

child_devices = self.obs_util.get_child_devices('Sub_1')
self.assertEquals(len(child_devices), 1)
self.assertEquals(child_devices['Sub_1'], [])

child_devices = self.obs_util.get_child_devices('XXX')
self.assertEquals(len(child_devices), 1)

0 comments on commit 81f5f0e

Please sign in to comment.