# Path: charms/reactive/relations.py
#     def entry_points():
# def endpoint_from_name(endpoint_name):
# def relation_from_name(relation_name):
# def endpoint_from_flag(flag):
# def relation_from_flag(flag):
# def relation_from_state(state):
#     def discover(cls):
#     def get_factory(cls, relation_name):
#     def from_name(cls, relation_name):
#     def from_flag(cls, state):
# def relation_factory(relation_name):
# def _relation_module(role, interface):
# def _find_relation_factory(module):
#     def __new__(cls, name, parents, dct):
#     def _accessor(field):
#         def __accessor(self):
#     def _startup(cls):
#             def depart_conv():
#     def __init__(self, relation_name, conversations=None):
#     def relation_name(self):
#     def from_state(cls, state):
#     def from_flag(cls, flag):
#     def from_name(cls, relation_name, conversations=None):
#     def _find_impl(cls, role, interface):
#     def _find_subclass(cls, module):
#     def conversations(self):
#     def conversation(self, scope=None):
#     def set_state(self, state, scope=None):
#     def remove_state(self, state, scope=None):
#     def is_state(self, state, scope=None):
#     def toggle_state(self, state, active=TOGGLE, scope=None):
#     def set_remote(self, key=None, value=None, data=None, scope=None, **kwdata):
#     def get_remote(self, key, default=None, scope=None):
#     def set_local(self, key=None, value=None, data=None, scope=None, **kwdata):
#     def get_local(self, key, default=None, scope=None):
#     def __init__(self, namespace, units, scope):
#     def _key(cls, namespace, scope):
#     def key(self):
#     def relation_name(self):
#     def relation_ids(self):
#     def join(cls, scope):
#     def depart(self):
#     def deserialize(cls, conversation):
#     def serialize(cls, conversation):
#     def load(cls, keys):
#     def set_state(self, state):
#     def remove_state(self, state):
#     def is_state(self, state):
#     def toggle_state(self, state, active=TOGGLE):
#     def set_remote(self, key=None, value=None, data=None, **kwdata):
#     def get_remote(self, key, default=None):
#     def set_local(self, key=None, value=None, data=None, **kwdata):
#     def get_local(self, key, default=None):
# def _migrate_conversations():  # noqa
# def relation_call(method, relation_name=None, flag=None, state=None, *args):
# ALL = object()
# TOGGLE = object()
#     GLOBAL = 'global'
#     SERVICE = 'service'
#     UNIT = 'unit'
# class RelationFactory(object):
# class scopes(object):
# class AutoAccessors(type):
# class RelationBase(RelationFactory, metaclass=AutoAccessors):
#     class states(StateList):
# class Conversation(object):


import os
import sys
import types
import mock
import unittest
from charmhelpers.core import hookenv
from charms.reactive import relations


class TestRelationBase(unittest.TestCase):
    def setUp(self):
        hookenv.cache = {}

    def test_find_subclass(self):
        self.assertIsNone(relations.RelationBase._find_subclass(unittest))
        self.assertIsNone(relations.RelationBase._find_subclass(relations))  # want strictly subclasses
        self.assertIs(
            relations.RelationBase._find_subclass(sys.modules[__name__]),
            DummyRelationSubclass)

    @mock.patch.object(relations.RelationBase, 'from_name')
    @mock.patch.object(relations.Conversation, 'load')
    @mock.patch.object(relations, '_get_flag_value')
    def test_from_state(self, get_flag_value, load, from_name):
        load.return_value = 'conv.load'
        get_flag_value.side_effect = [{'relation': 'relname', 'conversations': ['conv']}, None]
        from_name.side_effect = lambda rn, c: 'from_name(%s, %s)' % (rn, c)
        self.assertEqual(relations.RelationBase.from_flag('state'), 'from_name(relname, conv.load)')
        self.assertEqual(relations.RelationBase.from_flag('no-state'), None)

    @mock.patch.object(relations.hookenv, 'relation_to_role_and_interface')
    @mock.patch.object(relations.Conversation, 'join')
    @mock.patch.object(relations.RelationBase, '_find_impl')
    def test_from_name(self, _find_impl, join, relation_to_role_and_interface):
        relation_to_role_and_interface.return_value = ('role', 'interface')
        r1 = mock.Mock(name='R1')
        _find_impl.side_effect = [None, r1, None]

# Path: charms/reactive/relations.py
#     def entry_points():
# def endpoint_from_name(endpoint_name):
# def relation_from_name(relation_name):
# def endpoint_from_flag(flag):
# def relation_from_flag(flag):
# def relation_from_state(state):
#     def discover(cls):
#     def get_factory(cls, relation_name):
#     def from_name(cls, relation_name):
#     def from_flag(cls, state):
# def relation_factory(relation_name):
# def _relation_module(role, interface):
# def _find_relation_factory(module):
#     def __new__(cls, name, parents, dct):
#     def _accessor(field):
#         def __accessor(self):
#     def _startup(cls):
#             def depart_conv():
#     def __init__(self, relation_name, conversations=None):
#     def relation_name(self):
#     def from_state(cls, state):
#     def from_flag(cls, flag):
#     def from_name(cls, relation_name, conversations=None):
#     def _find_impl(cls, role, interface):
#     def _find_subclass(cls, module):
#     def conversations(self):
#     def conversation(self, scope=None):
#     def set_state(self, state, scope=None):
#     def remove_state(self, state, scope=None):
#     def is_state(self, state, scope=None):
#     def toggle_state(self, state, active=TOGGLE, scope=None):
#     def set_remote(self, key=None, value=None, data=None, scope=None, **kwdata):
#     def get_remote(self, key, default=None, scope=None):
#     def set_local(self, key=None, value=None, data=None, scope=None, **kwdata):
#     def get_local(self, key, default=None, scope=None):
#     def __init__(self, namespace, units, scope):
#     def _key(cls, namespace, scope):
#     def key(self):
#     def relation_name(self):
#     def relation_ids(self):
#     def join(cls, scope):
#     def depart(self):
#     def deserialize(cls, conversation):
#     def serialize(cls, conversation):
#     def load(cls, keys):
#     def set_state(self, state):
#     def remove_state(self, state):
#     def is_state(self, state):
#     def toggle_state(self, state, active=TOGGLE):
#     def set_remote(self, key=None, value=None, data=None, **kwdata):
#     def get_remote(self, key, default=None):
#     def set_local(self, key=None, value=None, data=None, **kwdata):
#     def get_local(self, key, default=None):
# def _migrate_conversations():  # noqa
# def relation_call(method, relation_name=None, flag=None, state=None, *args):
# ALL = object()
# TOGGLE = object()
#     GLOBAL = 'global'
#     SERVICE = 'service'
#     UNIT = 'unit'
# class RelationFactory(object):
# class scopes(object):
# class AutoAccessors(type):
# class RelationBase(RelationFactory, metaclass=AutoAccessors):
#     class states(StateList):
# class Conversation(object):


# Path: tests/test_relations.py
import os
import sys
import types
import mock
import unittest
from charmhelpers.core import hookenv
from charms.reactive import relations



class TestRelationBase(unittest.TestCase):
    def setUp(self):
        hookenv.cache = {}

    def test_find_subclass(self):
        self.assertIsNone(relations.RelationBase._find_subclass(unittest))
        self.assertIsNone(relations.RelationBase._find_subclass(relations))  # want strictly subclasses
        self.assertIs(
            relations.RelationBase._find_subclass(sys.modules[__name__]),
            DummyRelationSubclass)

    @mock.patch.object(relations.RelationBase, 'from_name')
    @mock.patch.object(relations.Conversation, 'load')
    @mock.patch.object(relations, '_get_flag_value')
    def test_from_state(self, get_flag_value, load, from_name):
        load.return_value = 'conv.load'
        get_flag_value.side_effect = [{'relation': 'relname', 'conversations': ['conv']}, None]
        from_name.side_effect = lambda rn, c: 'from_name(%s, %s)' % (rn, c)
        self.assertEqual(relations.RelationBase.from_flag('state'), 'from_name(relname, conv.load)')
        self.assertEqual(relations.RelationBase.from_flag('no-state'), None)

    @mock.patch.object(relations.hookenv, 'relation_to_role_and_interface')
    @mock.patch.object(relations.Conversation, 'join')
    @mock.patch.object(relations.RelationBase, '_find_impl')
    def test_from_name(self, _find_impl, join, relation_to_role_and_interface):
        relation_to_role_and_interface.return_value = ('role', 'interface')
        r1 = mock.Mock(name='R1')
        _find_impl.side_effect = [None, r1, None]

        join.return_value = 'conv.join'