コード例 #1
0
def test_warning_when_prediction_method_and_no_probabilities():
    """
    Test compute_eval_from_predictions logs a warning if a prediction method is provided
    but the predictions file doesn't contain probabilities.
    """
    lc = LogCapture()
    lc.begin()

    pred_path = join(_my_dir, 'other',
                     'test_compute_eval_from_predictions_predictions.tsv')
    input_path = join(_my_dir, 'other',
                      'test_compute_eval_from_predictions.jsonlines')

    # we need to capture stdout since that's what main() writes to
    compute_eval_from_predictions_cmd = [input_path, pred_path, 'pearson',
                                         'unweighted_kappa', '--method', 'highest']
    try:
        old_stdout = sys.stdout
        old_stderr = sys.stderr
        sys.stdout = mystdout = StringIO()
        sys.stderr = mystderr = StringIO()
        cefp.main(compute_eval_from_predictions_cmd)
        score_rows = mystdout.getvalue().strip().split('\n')
        err = mystderr.getvalue()
        print(err)
    finally:
        sys.stdout = old_stdout
        sys.stderr = old_stderr

    log_msg = ("skll.utilities.compute_eval_from_predictions: WARNING: A prediction "
               "method was provided, but the predictions file doesn't contain "
               "probabilities. Ignoring prediction method 'highest'.")

    eq_(lc.handler.buffer[-1], log_msg)
コード例 #2
0
    def test_unicode_messages_handled(self):
        msg = u'Ivan Krsti\u0107'
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args([])
        c.configure(options, Config())
        c.start()
        log = logging.getLogger("foobar.something")
        log.debug(msg)
        log.debug("ordinary string log")
        c.end()

        class Dummy:
            pass
        test = Dummy() 
        try:
            raise Exception(msg)
        except:
            err = sys.exc_info()
        (ec, ev, tb) = c.formatError(test, err)
        print ev
        if UNICODE_STRINGS:
            assert msg in ev
        else:
            assert msg.encode('utf-8') in ev
コード例 #3
0
 def test_logging_format_option(self):
     env = {'NOSE_LOGFORMAT': '++%(message)s++'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['logging_format'])
     c.configure(options, Config())
     eq_('++%(message)s++', c.logformat)
コード例 #4
0
 def test_logging_datefmt_option(self):
     env = {'NOSE_LOGDATEFMT': '%H:%M:%S'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['logging_datefmt'])
     c.configure(options, Config())
     eq_('%H:%M:%S', c.logdatefmt)
コード例 #5
0
    def setUp(self):
        self.data_dir = TestDataLocator.get_data_dir() + os.sep
        self.maxDiff = None

        # Log capturing
        self.log = LogCapture()
        self.log.logformat = '%(levelname)s: %(message)s'
        self.log.begin()
コード例 #6
0
ファイル: test_log.py プロジェクト: michaeltchapman/giftwrap
    def test_get_logger(self):
        lc = LogCapture()
        lc.begin()
        logger = log.get_logger()
        logger.debug('test-debug')
        logger.info('test-info')
        lc.end()

        self.assertEquals("giftwrap: INFO: test-info", lc.handler.buffer[0])
コード例 #7
0
ファイル: test_log.py プロジェクト: openstack/giftwrap
    def test_get_logger(self):
        lc = LogCapture()
        lc.begin()
        logger = logging.getLogger("giftwrap")
        logger.setLevel(logging.INFO)
        logger.debug("test-debug")
        logger.info("test-info")
        lc.end()

        self.assertEqual("giftwrap: INFO: test-info", lc.handler.buffer[0])
コード例 #8
0
ファイル: test_log.py プロジェクト: blueboxgroup/giftwrap
    def test_get_logger_debug(self):
        lc = LogCapture()
        lc.begin()
        logger = logging.getLogger('giftwrap')
        logger.setLevel(logging.DEBUG)
        logger.info('test-info')
        logger.debug('test-debug')
        lc.end()

        self.assertEquals("giftwrap: INFO: test-info", lc.handler.buffer[0])
        self.assertEquals("giftwrap: DEBUG: test-debug", lc.handler.buffer[1])
コード例 #9
0
    def test_default_options(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser)

        options, args = parser.parse_args(['default_options'])
        c.configure(options, Config())
        assert c.enabled
        eq_(LogCapture.logformat, c.logformat)
        eq_(LogCapture.clear, c.clear)
        eq_(LogCapture.filters, c.filters)
コード例 #10
0
 def test_captures_logging(self):
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, {})
     options, args = parser.parse_args([])
     c.configure(options, Config())
     c.start()
     log = logging.getLogger("foobar.something")
     log.debug("Hello")
     c.end()
     eq_(1, len(c.handler.buffer))
     eq_("Hello", c.handler.buffer[0].msg)
コード例 #11
0
    def setUp(self):
        self.data_dir = TestDataLocator.get_data_dir()
        self.maxDiff = None

        # Log capturing
        self.log = LogCapture()
        self.log.logformat = '%(levelname)s: %(message)s'
        self.log.begin()

        fname = os.path.join(self.data_dir, "paper_has_author.orm")
        model = NormaLoader(fname).model
        self.paper_has_author = ORMMinusModel(model=model)
        self.solution1 = self.paper_has_author.solution
コード例 #12
0
 def test_loglevel(self):
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, {})
     options, args = parser.parse_args(['--logging-level', 'INFO'])
     c.configure(options, Config())
     c.start()
     log = logging.getLogger("loglevel")
     log.debug("Hello")
     log.info("Goodbye")
     c.end()
     records = c.formatLogRecords()
     eq_(1, len(c.handler.buffer))
     eq_("loglevel: INFO: Goodbye", c.handler.buffer[0])
     eq_("loglevel: INFO: Goodbye", records[0])
コード例 #13
0
 def test_captures_logging(self):
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, {})
     options, args = parser.parse_args([])
     c.configure(options, Config())
     c.start()
     log = logging.getLogger("foobar.something")
     log.debug("Hello")
     c.end()
     eq_(1, len(c.handler.buffer))
     eq_("foobar.something: DEBUG: Hello", c.handler.buffer[0])
コード例 #14
0
 def test_logging_filter_exclude_and_include(self):
     env = {'NOSE_LOGFILTER': 'foo,-foo.bar'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['foo'])
     print options, args
     c.configure(options, Config())
     c.start()
     for name in ['foo.yes', 'foo.bar', 'foo.bar.no', 'blah']:
         log = logging.getLogger(name)
         log.info("Hello %s" % name)
     c.end()
     records = c.formatLogRecords()
     eq_(1, len(records))
     assert records[0].startswith('foo.yes:'), records[0]
コード例 #15
0
    def test_disable_option(self):
        parser = OptionParser()
        c = LogCapture()
        c.addOptions(parser)
        options, args = parser.parse_args(['test_can_be_disabled_long',
                                           '--nologcapture'])
        c.configure(options, Config())
        assert not c.enabled

        env = {'NOSE_NOLOGCAPTURE': 1}
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, env)
        options, args = parser.parse_args(['test_can_be_disabled'])
        c.configure(options, Config())
        assert not c.enabled
コード例 #16
0
 def test_logging_filter_exclude(self):
     env = {'NOSE_LOGFILTER': '-foo,-bar'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['foo'])
     print options, args
     c.configure(options, Config())
     c.start()
     for name in ['foobar.something', 'foo', 'foo.x', 'abara', 'bar.quux']:
         log = logging.getLogger(name)
         log.info("Hello %s" % name)
     c.end()
     records = c.formatLogRecords()
     eq_(2, len(records))
     assert records[0].startswith('foobar.something:'), records[0]
     assert records[1].startswith('abara:'), records[1]
コード例 #17
0
    def setUpClass(cls):
        cls.maxDiff = None
        cls.tempdir = tempfile.mkdtemp()

        # Log capturing
        cls.log = LogCapture()
        cls.log.logformat = '%(levelname)s: %(message)s'
        cls.log.begin()
コード例 #18
0
    def test_non_propagating_loggers_handled(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args([])
        c.configure(options, Config())

        logger = logging.getLogger('foo.yes')
        logger.propagate = False

        c.start()
        logger.debug("test message")
        c.end()

        records = c.formatLogRecords()
        eq_(1, len(records))
        assert records[0].startswith('foo.yes:'), records[0]
コード例 #19
0
 def test_custom_formatter(self):
     c = LogCapture()
     c.logformat = '++%(message)s++'
     c.start()
     log = logging.getLogger("foobar.something")
     log.debug("Hello")
     c.end()
     records = c.formatLogRecords()
     eq_(1, len(records))
     eq_("++Hello++", records[0])
コード例 #20
0
class NoseSeleniumBase(PluginTester, TestCase):
    activate = '--with-nose-selenium'  # enables the plugin
    plugins = [NoseSelenium(), LogCapture()]

    def makeSuite(self):
        class TC(TestCase):
            def runTest(self):
                raise ValueError("We should never get here")

        return TestSuite([TC()])
コード例 #21
0
 def test_consistent_mutables(self):
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser)
     c.start()
     log = logging.getLogger("mutable")
     mutable = { 'value': 1 }
     log.debug("%r", mutable)
     repr_1 = repr(mutable)
     mutable['value'] = 2
     log.debug("%r", mutable)
     repr_2 = repr(mutable)
     c.end()
     records = c.formatLogRecords()
     eq_("mutable: DEBUG: %s" % (repr_1,), records[0])
     eq_("mutable: DEBUG: %s" % (repr_2,), records[1])
コード例 #22
0
 def test_custom_formatter(self):
     c = LogCapture()
     c.logformat = '++%(message)s++'
     c.start()
     log = logging.getLogger("foobar.something")
     log.debug("Hello")
     c.end()
     records = c.formatLogRecords()
     eq_(1, len(records))
     eq_("++Hello++", records[0])
コード例 #23
0
 def test_logging_format_option(self):
     env = {'NOSE_LOGFORMAT': '++%(message)s++'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['logging_format'])
     c.configure(options, Config())
     eq_('++%(message)s++', c.logformat)
コード例 #24
0
 def test_logging_datefmt_option(self):
     env = {'NOSE_LOGDATEFMT': '%H:%M:%S'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['logging_datefmt'])
     c.configure(options, Config())
     eq_('%H:%M:%S', c.logdatefmt)
コード例 #25
0
ファイル: klogger_test.py プロジェクト: ashpool/ketchlip
def test_logging():
    c = LogCapture()
    parser = OptionParser()
    c.addOptions(parser, {})
    logger = klogger.get_logger("foo")
    logger = klogger.get_module_logger(__name__)
    c.start()

    logger.info("Goodbye")

    c.end()
    records = c.formatLogRecords()
    eq_("Goodbye", c.handler.buffer[0].msg)
    eq_("test.helpers.klogger_test", c.handler.buffer[0].name)
    eq_("test.helpers.klogger_test: INFO: Goodbye", records[0])
コード例 #26
0
 def test_consistent_mutables(self):
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser)
     c.start()
     log = logging.getLogger("mutable")
     mutable = { 'value': 1 }
     log.debug("%r", mutable)
     repr_1 = repr(mutable)
     mutable['value'] = 2
     log.debug("%r", mutable)
     repr_2 = repr(mutable)
     c.end()
     records = c.formatLogRecords()
     eq_("mutable: DEBUG: %s" % (repr_1,), records[0])
     eq_("mutable: DEBUG: %s" % (repr_2,), records[1])
コード例 #27
0
ファイル: test_log.py プロジェクト: omgjlk/giftwrap
    def test_get_logger(self):
        lc = LogCapture()
        lc.begin()
        logger = logging.getLogger('giftwrap')
        logger.setLevel(logging.INFO)
        logger.debug('test-debug')
        logger.info('test-info')
        lc.end()

        self.assertEqual("giftwrap: INFO: test-info", lc.handler.buffer[0])
コード例 #28
0
    def test_default_options(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser)

        options, args = parser.parse_args(['default_options'])
        c.configure(options, Config())
        assert c.enabled
        eq_(LogCapture.logformat, c.logformat)
        eq_(LogCapture.clear, c.clear)
        eq_(LogCapture.filters, c.filters)
コード例 #29
0
 def test_builtin_logging_filtering(self):
     c = LogCapture()
     c.logformat = '++%(message)s++'
     c.start()
     log = logging.getLogger("foobar.something")
     filtered = []
     class filter(object):
         def filter(record):
             filtered.append(record)
             return len(filtered) == 1
         filter = staticmethod(filter)
     c.handler.addFilter(filter)
     log.debug("Hello")
     log.debug("World")
     c.end()
     eq_(2, len(filtered))
     records = c.formatLogRecords()
     eq_(1, len(records))
     eq_("++Hello++", records[0])
コード例 #30
0
    def test_disable_option(self):
        parser = OptionParser()
        c = LogCapture()
        c.addOptions(parser)
        options, args = parser.parse_args(
            ['test_can_be_disabled_long', '--nologcapture'])
        c.configure(options, Config())
        assert not c.enabled

        env = {'NOSE_NOLOGCAPTURE': 1}
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, env)
        options, args = parser.parse_args(['test_can_be_disabled'])
        c.configure(options, Config())
        assert not c.enabled
コード例 #31
0
    def test_unicode_messages_handled(self):
        msg = u'Ivan Krsti\u0107'
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args([])
        c.configure(options, Config())
        c.start()
        log = logging.getLogger("foobar.something")
        log.debug(msg)
        log.debug("ordinary string log")
        c.end()

        class Dummy:
            pass

        test = Dummy()
        try:
            raise Exception(msg)
        except:
            err = sys.exc_info()
        (ec, ev, tb) = c.formatError(test, err)
        print ev
        if UNICODE_STRINGS:
            assert msg in ev
        else:
            assert msg.encode('utf-8') in ev
コード例 #32
0
 def test_logging_filter_exclude_and_include(self):
     env = {'NOSE_LOGFILTER': 'foo,-foo.bar'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['foo'])
     print options, args
     c.configure(options, Config())
     c.start()
     for name in ['foo.yes', 'foo.bar', 'foo.bar.no', 'blah']:
         log = logging.getLogger(name)
         log.info("Hello %s" % name)
     c.end()
     records = c.formatLogRecords()
     eq_(1, len(records))
     assert records[0].startswith('foo.yes:'), records[0]
コード例 #33
0
 def test_loglevel(self):
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, {})
     options, args = parser.parse_args(['--logging-level', 'INFO'])
     c.configure(options, Config())
     c.start()
     log = logging.getLogger("loglevel")
     log.debug("Hello")
     log.info("Goodbye")
     c.end()
     records = c.formatLogRecords()
     eq_(1, len(c.handler.buffer))
     eq_("Goodbye", c.handler.buffer[0].msg)
     eq_("loglevel: INFO: Goodbye", records[0])
コード例 #34
0
    def test_clears_all_existing_log_handlers(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args(['--logging-clear-handlers'])
        c.configure(options, Config())
        eq_(c.clear, True)

        def mktest():
            class TC(unittest.TestCase):
                def runTest(self):
                    pass
            test = TC()
            return test

        logging.getLogger().addHandler(StreamHandler(sys.stdout))
        log = logging.getLogger("dummy")
        log.addHandler(StreamHandler(sys.stdout))

        c.start()
        c.beforeTest(mktest())
        c.end()

        if py27:
            expect = ["<class 'nose.plugins.logcapture.MyMemoryHandler'>"]
        else:
            expect = ['nose.plugins.logcapture.MyMemoryHandler']
        eq_([str(c.__class__) for c in logging.getLogger().handlers],
            expect)
        eq_([str(c.__class__) for c in logging.getLogger("dummy").handlers],
            [])
コード例 #35
0
def test(ctx, paths='', failfast=False, verbose=False, skip_coverage=False):
    """
    Runs the unit tests

    Usage:
        inv dev.test --paths='api' --failfast
    """
    import unittest

    import nose
    from coverage import Coverage
    from nose.plugins.capture import Capture
    from nose.plugins.logcapture import LogCapture

    from config import set_config
    config = set_config('testing')

    from tests import prepare_database as tests_prepare_database

    class ConfiguringPlugin(nose.plugins.Plugin):
        enabled = True

        def configure(self, options, conf):
            pass

        def begin(self):
            tests_prepare_database()

    runner = unittest.TextTestRunner(verbosity=2 if verbose else 1)
    argv = ['nosetests']

    if failfast:
        argv.append('--stop')

    for path in paths.split(','):
        prefix = 'tests.'
        if not path:
            prefix = prefix[:-1]

        argv.append(prefix + path)

    plugins = [ConfiguringPlugin()]

    if config.nose.log_capturing:
        argv += [
            '--logging-clear-handlers',
            '--logging-format=(%(thread)d) %(name)s: %(levelname)s: %(message)s'
        ]
        plugins.append(LogCapture())

    if config.nose.stdout_capturing:
        plugins.append(Capture())

    os.chdir(os.path.join(config.project_dir, os.path.pardir))

    if not skip_coverage:
        cov = Coverage(
            source=[config.project_dir],
            omit=[
                'src/admin/*',
                'src/celery_tasks/*',
                'src/db/*',
                'src/tasks/*',
                'src/tests/*',
            ],
        )
        cov.start()

    nose.main(
        argv=argv,
        testRunner=runner,
        plugins=plugins,
        exit=False,
    )

    if not skip_coverage:
        directory = os.path.join(config.project_dir, '.coverage_report')
        print(f'\nSaving coverage report to "{os.path.abspath(directory)}"\n')

        cov.stop()
        cov.save()
        cov.html_report(directory=directory, title='WSP Coverage Report')
コード例 #36
0
class TestNormaLoader(TestCase):
    """ Unit tests for the NormaLoader class. """
    def setUp(self):
        self.data_dir = TestDataLocator.get_data_dir() + os.sep
        self.maxDiff = None

        # Log capturing
        self.log = LogCapture()
        self.log.logformat = '%(levelname)s: %(message)s'
        self.log.begin()

    def test_bad_filename_extension(self):
        """ Confirm that exception is raised when input file has .txt extension 
            rather than .orm extension. """
        with self.assertRaises(Exception) as ex:
            NormaLoader("test.txt")
        self.assertEqual(ex.exception.message,
                         "Input filename must have .orm extension.")

    def test_bad_root_element(self):
        """ Confirm that exception is raised when the root element of the
            XML is not <ormRoot:ORM2>. """
        with self.assertRaises(Exception) as ex:
            NormaLoader(self.data_dir + "bad_root_element.orm")
        self.assertEqual(ex.exception.message,
                         "Root of input file must be <ormRoot:ORM2>.")

    def test_no_model_element(self):
        """ Confirm that exception is raised when the XML does not contain an
            ORMModel element. 
        """
        with self.assertRaises(Exception) as ex:
            NormaLoader(self.data_dir + "no_model_element.orm")
        self.assertEqual(ex.exception.message,
                         "Cannot find <orm:ORMModel> in input file.")

    def test_empty_model(self):
        """ Confirm a successful parse on a small input file. """
        model = NormaLoader(self.data_dir + "empty_model.orm").model
        self.assertEqual(model.object_types.count(), 0)
        self.assertEqual(model.fact_types.count(), 0)
        self.assertEqual(model.constraints.count(), 0)

    def test_adding_invalid_element(self):
        """ Confirm exception is raised if an invalid object is passed to
            the _add() method."""
        loader = NormaLoader(self.data_dir + "empty_model.orm")
        with self.assertRaises(Exception) as ex:
            loader._add(ModelElement(uid="123", name="ABC"))
        self.assertEqual(ex.exception.message, "Unexpected model element type")

    def test_subtypes(self):
        """ Confirm that subtype derivation rule omission note
            is added to self.omissions and that subtype constraints load 
            properly. Also confirm that if inclusive-or or XOR constraints
            are present on a subtype, they are reported in the omissions. """
        loader = NormaLoader(self.data_dir + "subtype_with_derivation.orm")
        model = loader.model

        self.assertItemsEqual(loader.omissions, [
            "Subtype derivation rule for B",
            "Subtype exclusion constraint ExclusiveOrConstraint1",
            "Subtype inclusive-or constraint InclusiveOrConstraint1",
            "Subtype inclusive-or constraint InclusiveOrConstraint2"
        ])

        cons1 = model.constraints.get("BIsASubtypeOfA")
        self.assertIs(cons1.subtype, model.object_types.get("B"))
        self.assertIs(cons1.supertype, model.object_types.get("A"))
        self.assertEquals(cons1.covers, [cons1.subtype, cons1.supertype])
        self.assertTrue(cons1.idpath)

        self.assertFalse(model.constraints.get("BIsASubtypeOfC").idpath)

    def test_subtypefact_constraints(self):
        """ Confirm IUC and mandatory constraints on implicit subtype fact types
            are ignored, because those fact types are ignored. """
        loader = NormaLoader(self.data_dir + "subtype_with_derivation.orm")
        model = loader.model

        # Note: the mandatory and uniqueness constraints below are on the
        # reference fact types (e.g. ZHasZId)
        expected = [
            'CIsASubtypeOfZ', 'AIsASubtypeOfZ', 'BIsASubtypeOfC',
            'BIsASubtypeOfA', 'SimpleMandatoryConstraint7',
            'InternalUniquenessConstraint13', 'InternalUniquenessConstraint14',
            'SimpleMandatoryConstraint1', 'InternalUniquenessConstraint1',
            'InternalUniquenessConstraint2', 'SimpleMandatoryConstraint3',
            'InternalUniquenessConstraint5', 'InternalUniquenessConstraint6'
        ]
        actual = [cons.name for cons in model.constraints]

        self.assertItemsEqual(actual, expected)

    def test_subtype_exception(self):
        """ Confirm subtype exception fires for corrupted data. """
        with self.assertRaises(Exception) as ex:
            loader = NormaLoader(self.data_dir + "corrupted_subtype.orm")
        self.assertEquals(ex.exception.message,
                          "Cannot load subtype constraint.")

    def test_load_object_types(self):
        """ Test of object type load. """
        self.log.beforeTest(None)
        loader = NormaLoader(self.data_dir + "object_type_tests.orm")
        model = loader.model

        # No derivation rules
        self.assertItemsEqual(loader.omissions, [])
        self.assertItemsEqual(self.log.formatLogRecords(), [])

        # Overall count
        self.assertEqual(model.object_types.count(), 10)

        # Independent Entity
        this = model.object_types.get("D")
        self.assertTrue(this.independent)
        self.assertIs(this.identifying_constraint,
                      model.constraints.get("InternalUniquenessConstraint7"))
        self.assertIsInstance(this, ObjectType.EntityType)

        # Non-independent Entity
        this = model.object_types.get("C")
        self.assertFalse(this.independent)

        # Independent value
        this = model.object_types.get("V2")
        self.assertTrue(this.independent)
        self.assertEquals(this.uid, "_FD295AC2-D845-48E4-9E09-2E48EC99E3F3")
        self.assertIsInstance(this, ObjectType.ValueType)

        # Non-independent value
        this = model.object_types.get("V1")
        self.assertFalse(this.independent)

        # Implicit value (created by unary fact type): should not be loaded
        this = model.object_types.get("A exists")
        self.assertIsNone(this)

        # Objectified Independent
        this = model.object_types.get("CHasV1")
        self.assertTrue(this.independent)
        self.assertIsInstance(this, ObjectType.ObjectifiedType)

        # Objectified Non-independent
        this = model.object_types.get("V1HasV2")
        nested = model.fact_types.get("V1HasV2")
        self.assertFalse(this.independent)
        self.assertIs(this.identifying_constraint,
                      model.constraints.get("InternalUniquenessConstraint14"))
        self.assertIs(this.nested_fact_type, nested)

        # Implicit Objectified (Created by ternary, should not load)
        this = model.object_types.get("V1HasDHasV2")
        self.assertIsNone(this)

        self.log.afterTest(None)

    def test_played_roles(self):
        """ Confirm that object types know the list of roles they play. """
        model = NormaLoader(self.data_dir + "object_type_tests.orm").model

        obj_type0 = model.object_types.get("B")
        obj_type1 = model.object_types.get("V1HasV2")
        obj_type2 = model.object_types.get("D")

        self.assertItemsEqual(obj_type0.roles, [])

        r1 = model.fact_types.get("V1HasV2Exists").roles[0]

        self.assertItemsEqual(obj_type1.roles, [r1])

        r1 = model.fact_types.get("V1HasDHasV2").roles[1]
        r2 = model.fact_types.get("DHasDId").roles[0]

        self.assertItemsEqual(obj_type2.roles, [r1, r2])

    def test_data_type_load(self):
        """ Confirm data types are loaded properly for Value Types. """
        model = NormaLoader(self.data_dir + "data_types.orm").model
        ot = model.object_types

        self.assertIsInstance(ot.get("A").domain,
                              Domain.StringDomain)  # data type undefined
        self.assertIsInstance(ot.get("B").domain,
                              Domain.BoolDomain)  # True or false
        self.assertIsInstance(ot.get("C").domain,
                              Domain.BoolDomain)  # Yes or no
        self.assertIsInstance(ot.get("D").domain,
                              Domain.IntegerDomain)  # auto counter
        self.assertIsInstance(ot.get("E").domain, Domain.FloatDomain)  # float
        self.assertIsInstance(ot.get("Special").domain,
                              Domain.FloatDomain)  # float
        self.assertIsInstance(ot.get("F").domain, Domain.FloatDomain)  # money
        self.assertIsInstance(ot.get("G").domain,
                              Domain.IntegerDomain)  # big int
        self.assertIsInstance(ot.get("H").domain,
                              Domain.DateTimeDomain)  # timestamp
        self.assertIsInstance(ot.get("I").domain, Domain.DateDomain)  # date
        self.assertIsInstance(ot.get("J").domain, Domain.TimeDomain)  # time
        self.assertIsInstance(ot.get("K").domain, Domain.StringDomain)  # text

        # Confirm for A and K that prefix is 'A' and 'K'
        obj = ot.get("A")
        actual = obj.domain.draw(2)
        expect = ['A0', 'A1']
        self.assertItemsEqual(actual, expect)

        obj = ot.get("K")
        actual = obj.domain.draw(2)
        expect = ['K0', 'K1']
        self.assertItemsEqual(actual, expect)

    def test_unknown_data_type(self):
        """ Confirm that domain defaults to StringDomain() if the actual type 
            is unexpected. """
        model = NormaLoader(self.data_dir + "unknown_data_types.orm").model

        obj = model.object_types.get("A")
        self.assertIsInstance(obj.domain, Domain.StringDomain)
        self.assertItemsEqual(obj.domain.draw(1), ["A0"])

        obj = model.object_types.get("B")
        self.assertIsInstance(obj.domain, Domain.StringDomain)
        self.assertItemsEqual(obj.domain.draw(1), ["B0"])

    def test_value_constraint_on_types(self):
        """ Confirm that value constraints on value types are loaded. """
        model = NormaLoader(self.data_dir +
                            "test_value_type_value_constraint.orm").model
        cons1 = model.constraints.get("VC_A")

        self.assertEquals(cons1.uid, "_9F61B75E-FB59-456F-97A9-E4CF104FABE5")
        self.assertIs(cons1.covers[0], model.object_types.get("A"))

        expected = set([1, 2, 6] + range(10, 20) + range(101, 200))
        self.assertItemsEqual(cons1.domain.draw(112), expected)
        self.assertEquals(cons1.size, 112)

    def test_load_fact_types(self):
        """ Confirm fact types load successfully. """
        loader = NormaLoader(self.data_dir + "fact_type_tests.orm")
        model = loader.model

        # Confirm reference scheme fact type loads
        ftype1 = model.fact_types.get("AHasAId")
        self.assertEquals(ftype1.uid, "_8C96FD40-5E82-4E8F-B5EE-C6CEE8BCF74B")
        self.assertIsInstance(ftype1, FactType)

        # Confirm derivation rule added to omissions
        self.assertItemsEqual(loader.omissions, [
            "Fact type derivation rule for AHasB",
            "Fact type derivation rule for AHasAId"
        ])

        # Check role player
        typea = model.object_types.get("A")
        typeb = model.object_types.get("B")
        ahasb = model.fact_types.get("AHasB")
        self.assertIs(ahasb.roles[0].player, typea)
        self.assertIs(ahasb.roles[1].player, typeb)

        # Check role fact type
        self.assertIs(ahasb.roles[0].fact_type, ahasb)
        self.assertIs(ahasb.roles[1].fact_type, ahasb)

        # Check that implicit role added to unary is removed
        aexists = model.fact_types.get("AExists")
        self.assertIs(aexists.roles[0].player, typea)
        self.assertEquals(aexists.arity(), 1)

        # Test role value constraint
        cons1 = model.constraints.get("RoleValueConstraint1")

        expected = ['A', 'Dog', '3.567', '12/23/2014']
        self.assertItemsEqual(cons1.domain.draw(4), expected)

    def test_forced_implicit(self):
        """ Exercise branch in _load_fact_types when arity() = 0. """
        loader = NormaLoader(self.data_dir + "forced_implicit_binary.orm")
        model = loader.model

        # The object types are both marked implicit so the corresponding
        # fact type should not load either.
        self.assertEquals(model.object_types.count(), 0)
        self.assertEquals(model.fact_types.count(), 0)

    def test_derivation_source(self):
        """ Confirm depricated DerivationSource element is ignored. """
        self.log.beforeTest(None)
        loader = NormaLoader(self.data_dir + "derivation_source.orm")

        expected = ["Role derivation rule within AHasB"]

        # Check omissions array
        self.assertItemsEqual(loader.omissions, expected)

        # Check log contents
        expected = ["WARNING: 1 model element was ignored while loading derivation_source.orm."] + \
                   ["INFO: Ignored " + expected[0]]

        self.assertItemsEqual(self.log.formatLogRecords(), expected)

        self.log.afterTest(None)

    def test_constraints_omitted(self):
        """ Confirm omitted constraints get saved to omissions list."""
        self.log.beforeTest(None)
        loader = NormaLoader(self.data_dir + "omitted_constraints.orm")

        expected = [
            "Exclusion constraint ExclusionConstraint1",
            "Exclusion constraint ExclusiveOrConstraint1",
            "Ring constraint RingConstraint1",
            "Value comparison constraint ValueComparisonConstraint1"
        ]

        # Check omissions array
        self.assertItemsEqual(loader.omissions, expected)

        # Check log contents
        expected = ["WARNING: 4 model elements were ignored while loading omitted_constraints.orm."] + \
                   ["INFO: Ignored " + msg for msg in expected]

        self.assertItemsEqual(self.log.formatLogRecords(), expected)

        self.log.afterTest(None)

    def test_subset_constraint(self):
        """ Confirm subset constraints load correctly. """
        fname = TestDataLocator.path("subset_constraint.orm")
        loader = NormaLoader(fname, deontic=True)
        model = loader.model

        cons1 = model.constraints.get("SubsetConstraint1")
        cons2 = model.constraints.get("SubsetConstraint2")
        cons3 = model.constraints.get("SubsetConstraint3")
        cons4 = model.constraints.get("SubsetConstraint4")

        obj_a = model.object_types.get("A")
        obj_b = model.object_types.get("B")
        ahasb = model.fact_types.get("AHasB")
        alikesb = model.fact_types.get("ALikesB")
        aplus = model.fact_types.get("CPlusAPlusB")
        aand = model.fact_types.get("AAndBAndC")

        # Check modality
        self.assertTrue(cons1.alethic)
        self.assertFalse(cons2.alethic)

        # Check unary subset
        self.assertEquals(len(cons1.superset), 1)
        self.assertEquals(len(cons1.subset), 1)
        self.assertIs(cons1.subset[0].player, obj_a)
        self.assertIs(cons1.superset[0].player, obj_a)
        self.assertIs(cons1.subset[0].fact_type, ahasb)
        self.assertIs(cons1.superset[0].fact_type, alikesb)
        self.assertItemsEqual(cons1.covers, cons1.subset + cons1.superset)

        # Check binary subset
        self.assertEquals(len(cons4.superset), 2)
        self.assertEquals(len(cons4.subset), 2)
        self.assertIs(cons4.subset[0].fact_type, aplus)
        self.assertIs(cons4.superset[1].fact_type, aand)
        self.assertIs(cons4.subset[0].player, cons4.superset[0].player)
        self.assertIs(cons4.subset[1].player, cons4.superset[1].player)
        self.assertIs(cons4.subset[1].player, obj_b)

        # Check ternary subset
        self.assertEquals(len(cons3.superset), 3)
        self.assertEquals(len(cons3.subset), 3)
        self.assertIs(cons3.subset[0].fact_type, aplus)
        self.assertIs(cons3.superset[2].fact_type, aand)
        self.assertIs(cons3.subset[2].player, cons3.subset[2].player)

        self.assertItemsEqual(loader.omissions, [])

    def test_partial_subset(self):
        """ Confirm exception fires for invalid subset constraints. """
        with self.assertRaises(Exception) as ex:
            loader = NormaLoader(self.data_dir + "partial_subset.orm")
        self.assertEquals(
            ex.exception.message,
            "Subset constraint SubsetConstraint1 does not have exactly two role sequences"
        )

    def test_implicit_role(self):
        """ Confirm constraint that covers implicit role is removed. """
        model = NormaLoader(self.data_dir + "test_implicit_roles.orm").model
        self.assertIsNone(model.constraints.get("SubsetConstraint1"))

    def test_deprecated_join(self):
        """ Confirm exception fires for models containing deprecated join constraint. """
        with self.assertRaises(Exception) as ex:
            loader = NormaLoader(self.data_dir + "deprecated_join.orm")
        self.assertEquals(
            ex.exception.message,
            "Subset constraint SubsetConstraint1 has deprecated join rule.")

    def test_join_subset_omission(self):
        """ Confirm that join subset constraints are (for now) omitted. """
        loader = NormaLoader(self.data_dir + "join_subset_omission.orm")
        self.assertItemsEqual(loader.omissions, [
            "Subset constraint SubsetConstraint1 because its join path does not have exactly one JoinPath node."
        ])

        cons = loader.model.constraints.get("SubsetConstraint1")
        self.assertIsNone(cons)

    def test_uniqueness_constraint(self):
        """ Confirm uniqueness constraints load properly. """
        fname = TestDataLocator.path("uniqueness_constraints.orm")
        model = NormaLoader(fname, deontic=True).model

        int_cons1 = model.constraints.get("InternalUniquenessConstraint4")
        int_cons2 = model.constraints.get("InternalUniquenessConstraint1")
        int_cons3 = model.constraints.get("InternalUniquenessConstraint9")
        ext_cons1 = model.constraints.get("ExternalUniquenessConstraint1")
        ext_cons2 = model.constraints.get("ExternalUniquenessConstraint2")

        obj_a = model.object_types.get("A")
        obj_b = model.object_types.get("B")
        obj_z = model.object_types.get("Z")
        ahasb = model.fact_types.get("AHasB")
        alikesb = model.fact_types.get("ALikesB")
        tern = model.fact_types.get("AAndAHoldsB")

        # Check uid
        self.assertEquals(int_cons1.uid,
                          "_22FD96ED-BE72-4859-8DA0-1A0C98381FEF")

        # Check internal attribute
        self.assertTrue(int_cons1.internal)
        self.assertFalse(ext_cons1.internal)

        # Check modality
        self.assertTrue(int_cons1.alethic)
        self.assertFalse(ext_cons2.alethic)

        # Check Covers sequence
        self.assertEquals(len(int_cons1.covers), 1)
        self.assertIs(int_cons1.covers[0].player, obj_a)
        self.assertIs(int_cons1.covers[0].fact_type, ahasb)

        self.assertEquals(len(ext_cons2.covers), 3)
        self.assertIs(ext_cons2.covers[0].player, obj_a)
        self.assertIs(ext_cons2.covers[1].player, obj_b)
        self.assertIs(ext_cons2.covers[2].player, obj_b)
        self.assertIs(ext_cons2.covers[1].fact_type, tern)
        self.assertIs(ext_cons2.covers[2].fact_type, alikesb)

        # Confirm implicit constraints excluded
        self.assertIsNone(
            model.constraints.get("InternalUniquenessConstraint2"))
        self.assertEquals(model.constraints.count(), 8)

        # Test preferred identifier.
        self.assertIsNone(int_cons2.identifier_for)  # implicit object type

        # Test preferred identifier
        self.assertIs(int_cons3.identifier_for, obj_z)
        self.assertIs(obj_z.identifying_constraint, int_cons3)

    def test_frequency_constraint(self):
        """ Confirm frequency constraints load properly. """
        model = NormaLoader(self.data_dir + "frequency_constraint.orm").model

        cons1 = model.constraints.get("FrequencyConstraint1")
        cons2 = model.constraints.get("FrequencyConstraint2")
        cons3 = model.constraints.get("FrequencyConstraint3")

        obj_a = model.object_types.get("A")
        obj_b = model.object_types.get("B")
        ahasb = model.fact_types.get("AHasB")
        alikesb = model.fact_types.get("ALikesB")

        # Check frequencies
        self.assertEquals(cons1.min_freq, 1)
        self.assertEquals(cons1.max_freq, 3)

        self.assertEquals(cons2.min_freq, 2)
        self.assertEquals(cons2.max_freq, 2)

        self.assertEquals(cons3.min_freq, 3)
        self.assertEquals(cons3.max_freq, float('inf'))

        # Check covered roles
        self.assertEquals(len(cons1.covers), 1)
        self.assertIs(cons1.covers[0].player, obj_b)
        self.assertIs(cons1.covers[0].fact_type, ahasb)

        self.assertEquals(len(cons2.covers), 2)

        self.assertEquals(len(cons3.covers), 2)
        self.assertIs(cons3.covers[0].fact_type, alikesb)
        self.assertIs(cons3.covers[1].fact_type, ahasb)

        # Check internal property
        self.assertTrue(cons1.internal)
        self.assertTrue(cons2.internal)
        self.assertFalse(cons3.internal)

    def test_bad_role_sequence_node(self):
        """ Confirm exception fires for invalid node in RoleSequence. """
        with self.assertRaises(Exception) as ex:
            loader = NormaLoader(self.data_dir + "bad_role_sequence.orm")
        self.assertEquals(
            ex.exception.message, "Uniqueness constraint " +
            "ExternalUniquenessConstraint1 has unexpected role sequence.")

    def test_freq_on_unary(self):
        """ Confirm loader ignores frequency constraint on unary.  
            it ignores the constraint because NORMA moves the constraint
            to the implicit role of the implicit binarized fact type. """
        loader = NormaLoader(self.data_dir + "implicit_freq_constraint.orm")
        model = loader.model
        self.assertIsNone(model.constraints.get("FrequencyConstraint2"))

        # The 1 constraint is the internal UC on the unary (implicit)
        self.assertEquals(model.constraints.count(), 1)

        self.assertEquals(model.fact_types.get("AExists").arity(), 1)

    def test_mandatory(self):
        """ Confirm mandatory constraints are successfully loaded. """
        loader = NormaLoader(self.data_dir + "mandatory_constraint.orm")
        model = loader.model

        # Test implied
        cons1 = model.constraints.get("ImpliedMandatoryConstraint2")
        self.assertIsNone(cons1)  # Implied due to disjunctive mandatory

        cons2 = model.constraints.get("SimpleMandatoryConstraint4")
        self.assertIsNone(cons2)  # Implied due to objectification

        # Confirm constraint count
        self.assertEquals(model.constraints.count(), 9)

        # Check loaded mandatories
        cons = model.constraints.of_type(Constraint.MandatoryConstraint)
        self.assertEquals(len(cons), 3)

        s1 = model.constraints.get("SimpleMandatoryConstraint1")
        s2 = model.constraints.get("SimpleMandatoryConstraint2")
        i1 = model.constraints.get("InclusiveOrConstraint1")

        fact_type1 = model.fact_types.get("EHasEId")
        self.assertTrue(s1.simple)
        self.assertEquals(len(s1.covers), 1)
        self.assertIs(s1.covers[0], fact_type1.roles[0])
        self.assertTrue(fact_type1.roles[0].mandatory)
        self.assertFalse(fact_type1.roles[1].mandatory)

        fact_type2 = model.fact_types.get("EHasB")
        self.assertTrue(s2.simple)
        self.assertEquals(len(s2.covers), 1)
        self.assertIs(s2.covers[0], fact_type2.roles[0])
        self.assertTrue(fact_type2.roles[0].mandatory)
        self.assertFalse(fact_type2.roles[1].mandatory)

        role1 = model.fact_types.get("EHasB").roles[1]
        role2 = model.fact_types.get("BIsCool").roles[0]
        self.assertFalse(i1.simple)
        self.assertEquals(len(i1.covers), 2)
        self.assertItemsEqual(i1.covers, [role1, role2])

        # For inclusive-or, neither covered role should have "mandatory" true
        self.assertFalse(role1.mandatory)
        self.assertFalse(role2.mandatory)

        # Confirm nothing ignored
        self.assertItemsEqual(loader.omissions, [])

    def test_role_names(self):
        """ Confirm role names are generated properly. """
        model = NormaLoader(self.data_dir + "role_names.orm").model

        ahasb = model.fact_types.get("AHasB")
        self.assertEquals(ahasb.roles[0].name, "A")
        self.assertEquals(ahasb.roles[1].name, "B")

        alikesb = model.fact_types.get("ALikesB")
        self.assertEquals(alikesb.roles[0].name, "A")
        self.assertEquals(alikesb.roles[1].name, "Likee")

        tern = model.fact_types.get("AAndALikeB")
        self.assertEquals(tern.roles[0].name, "R2")
        self.assertEquals(tern.roles[1].name, "A")
        self.assertEquals(tern.roles[2].name, "B")

    def test_invalid_value_constraint(self):
        """ Test that invalid value constraint is ignored. """
        loader = NormaLoader(self.data_dir + "invalid_value_constraint.orm")
        model = loader.model

        actual = loader.omissions
        expected = [
            "Value constraint VC1 because value constraints only support integer ranges"
        ]
        self.assertItemsEqual(actual, expected)

        actual = [cons.name for cons in model.constraints]
        expected = ["VC2"]
        self.assertItemsEqual(actual, expected)

    def test_cardinality_constraints(self):
        """ Test loading of cardinality constraints. """
        fname = TestDataLocator.path("test_cardinality_constraint.orm")
        loader = NormaLoader(fname, deontic=True)
        model = loader.model

        cons1 = model.constraints.get("CC1")
        self.assertTrue(cons1.alethic)
        self.assertEquals(cons1.ranges[0].lower, 0)
        self.assertEquals(cons1.ranges[0].upper, 4)
        self.assertItemsEqual(cons1.covers, [model.object_types.get("A")])

        cons2 = model.constraints.get("CC2")
        self.assertTrue(cons2.alethic)
        self.assertEquals(cons2.ranges[0].lower, 2)
        self.assertEquals(cons2.ranges[0].upper, None)
        self.assertItemsEqual(cons2.covers, [model.object_types.get("B")])

        cons3 = model.constraints.get("CC3")
        role = model.fact_types.get("AExists").roles[0]
        self.assertTrue(cons3.alethic)
        self.assertEquals(cons3.ranges[0].lower, 4)
        self.assertEquals(cons3.ranges[0].upper, 7)
        self.assertItemsEqual(cons3.covers, [role])

        cons4 = model.constraints.get("CC4")
        role = model.fact_types.get("BHopes").roles[0]
        self.assertFalse(cons4.alethic)
        self.assertEquals(cons4.ranges[0].lower, 4)
        self.assertEquals(cons4.ranges[0].upper, 4)
        self.assertItemsEqual(cons4.covers, [role])

        cons5 = model.constraints.get("CC5")
        role = model.fact_types.get("BDances").roles[0]
        self.assertTrue(cons5.alethic)
        self.assertEquals(len(cons5.ranges), 4)

        self.assertEquals(cons5.ranges[0].lower, 0)
        self.assertEquals(cons5.ranges[0].upper, 2)
        self.assertEquals(cons5.ranges[1].lower, 5)
        self.assertEquals(cons5.ranges[1].upper, 5)
        self.assertEquals(cons5.ranges[2].lower, 8)
        self.assertEquals(cons5.ranges[2].upper, 10)
        self.assertEquals(cons5.ranges[3].lower, 12)
        self.assertEquals(cons5.ranges[3].upper, None)

        self.assertItemsEqual(cons5.covers, [role])

    def test_bad_cardinality_constraint_1(self):
        """ Test loading of file with two cardinality constraints in one node. """

        with self.assertRaises(ValueError) as ex:
            NormaLoader(self.data_dir + "bad_cardinality_constraint_1.orm")

        self.assertEquals(ex.exception.message,
                          "Unexpected cardinality constraint format")

    def test_bad_cardinality_constraint_2(self):
        """ Test loading of file with badly named cardinality constraint node. """

        loader = NormaLoader(self.data_dir +
                             "bad_cardinality_constraint_2.orm")
        self.assertItemsEqual(loader.unexpected, ["BadCardinalityConstraint"])

    def test_bad_cardinality_constraint_3(self):
        """ Test loading of file with badly named ranges node. """

        loader = NormaLoader(self.data_dir +
                             "bad_cardinality_constraint_3.orm")
        model = loader.model
        cons = model.constraints.get("C1")
        self.assertEquals(cons.ranges, [])

    def test_bad_value_constraint(self):
        """ Test loading of file with badly named value constraint node. """

        loader = NormaLoader(self.data_dir + "bad_value_constraint.orm")
        self.assertItemsEqual(loader.unexpected, ["BadValueConstraint"])

    def test_card_and_value_constraint_on_implicit_type(self):
        """ Confirm that cardinality and value constraints on implicit types
            are ignored. This model contains one of each on an implicit 
            boolean object type. """
        loader = NormaLoader(self.data_dir + "constraint_on_implicit_type.orm")
        model = loader.model
        self.assertEquals(model.constraints.count(), 1)
        self.assertIsNotNone(model.constraints.get("IUC1"))

    def test_unexpected_constraint_node(self):
        """ Confirm the loader catches an unexpected constraint node. """
        self.log.beforeTest(None)

        loader = NormaLoader(self.data_dir + "unexpected_constraint_node.orm")
        self.assertItemsEqual(loader.unexpected, ["NewConstraint"])

        # Check log contents
        expected = ["WARNING: 1 XML node was unexpected while loading unexpected_constraint_node.orm."] + \
                   ["INFO: Unexpected NewConstraint"]

        self.assertItemsEqual(self.log.formatLogRecords(), expected)

        self.log.afterTest(None)

    def test_constraint_covers_both_implied_and_explicit_role(self):
        """ Test a constraint that covers both an implied and an explicit  
            role, which is a VERY UNLIKELY scenario. """
        loader = NormaLoader(self.data_dir + \
            "constraint_covers_both_implied_and_regular_roles.orm.orm")
        model = loader.model

        expected = [
            "Uniqueness constraint EUC1 because it covers implied and explicit roles"
        ]

        self.assertIsNone(model.constraints.get("EUC1"))
        self.assertEquals(model.constraints.count(), 2)
        self.assertItemsEqual(loader.omissions, expected)

    def test_deontic_constraints(self):
        """ Test that deontic constraints are correctly ignored. """
        fname = TestDataLocator.path("deontic_constraints.orm")
        loader = NormaLoader(fname, deontic=False)
        model = loader.model

        self.assertEquals(model.constraints.count(), 2)
        self.assertIsNotNone(model.constraints.get("IUC1"))
        self.assertIsNotNone(model.constraints.get("IUC_unary"))
        self.assertEquals(loader.omissions, [])

        loader = NormaLoader(fname, deontic=True)
        model = loader.model

        self.assertEquals(model.constraints.count(), 3)
        self.assertIsNotNone(model.constraints.get("IUC2d"))
        self.assertItemsEqual(loader.omissions, ["Exclusion constraint EXC1"])

    def test_deontic_cardinality(self):
        """ Test that deontic modality is recognized for cardinality constraints."""
        fname = TestDataLocator.path("deontic_cardinality.orm")
        loader = NormaLoader(fname, deontic=False)
        model = loader.model

        # Only the unary IUC should not be ignored
        self.assertEquals(model.constraints.count(), 1)
        self.assertIsNotNone(model.constraints.get("IUC_unary"))

    def test_join_rule_with_no_join_path(self):
        """ Test <JoinRule> not followed by a <JoinPath>. """
        fname = TestDataLocator.path("join_rule_no_join_path.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("ExternalUniquenessConstraint1")
        self.assertIsNone(cons)

        expected = "Uniqueness constraint ExternalUniquenessConstraint1 because its join path does not have exactly one JoinPath node."
        self.assertEquals(loader.omissions, [expected])

    def test_join_rule_with_subquery(self):
        """ Test <JoinRule> that contains a <SubQueries> node. """
        fname = TestDataLocator.path("join_rule_with_subquery.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FC1_with_subquery")
        self.assertIsNone(cons)

        expected = "Frequency constraint FC1_with_subquery because its join path has a JoinPath node with an unsupported child node: Subqueries."
        self.assertEquals(loader.omissions, [expected])

    def test_join_rule_with_no_role_path(self):
        """ Test <JoinRule> that contains no <RolePath> node. """
        fname = TestDataLocator.path("join_rule_no_role_path.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")
        self.assertIsNone(cons)

        expected = "Frequency constraint FrequencyConstraint1 because its join path does not have exactly one RolePath node."
        self.assertEquals(loader.omissions, [expected])

    def test_join_rule_with_unsupported_splits(self):
        """ Test <JoinRule> that contains negated split paths and combination
            operators other than AND. """
        fname = TestDataLocator.path("join_rule_negated_split.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons_neg = model.constraints.get("EUC_negated")
        cons_or = model.constraints.get("EUC_or")

        self.assertIsNone(cons_neg)
        self.assertIsNone(cons_or)

        expected = [
            "Uniqueness constraint EUC_negated because its join path has a negated path split.",
            "Uniqueness constraint EUC_or because its join path combines paths with an operator other than AND."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_subpath_with_bad_child_node(self):
        """ Test <SubPath> node with bad child node. Specifically, this test
            case has a nested <SubPaths> node under a <SubPath>, which we do 
            not support. """
        fname = TestDataLocator.path("bad_subpath_child_node.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("EUC1")
        self.assertIsNone(cons)

        expected = [
            "Uniqueness constraint EUC1 because its join path has a SubPaths node with an unsupported child node: BadSubPath."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_pathed_roles_with_bad_child_node(self):
        """ Test <PathedRoles> node with bad child node. """
        fname = TestDataLocator.path("join_rule_pathed_roles_bad_child.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")
        self.assertIsNone(cons)

        expected = [
            "Frequency constraint FrequencyConstraint1 because its join path has a PathedRoles node with an unsupported child node: PathedRole2."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_join_rule_covering_implicit_roles(self):
        """ Test <PathedRoles> node that include implicit roles. """
        fname = TestDataLocator.path("join_rule_covering_implicit_roles.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("EUC1")
        self.assertIsNone(cons)  # Not loaded because it covers implicit roles

        expected = [
            "Uniqueness constraint EUC1 because its join path includes an implicit role."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_pathed_role_with_value_restriction_child_node(self):
        """ Test <PathedRole> node with bad child node. """
        fname = TestDataLocator.path(
            "join_rule_pathed_role_with_value_restriction.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")
        self.assertIsNone(cons)

        expected = [
            "Frequency constraint FrequencyConstraint1 because its join path has a PathedRole node with an unsupported child node: ValueRestriction."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_pathed_role_with_outer_join(self):
        """ Test <PathedRole> node with outer join. """
        fname = TestDataLocator.path(
            "join_rule_pathed_role_with_outer_join.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")
        self.assertIsNone(cons)

        expected = [
            "Frequency constraint FrequencyConstraint1 because its join path includes an outer join."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_pathed_role_with_negated_join(self):
        """ Test <PathedRole> node with negated join. """
        fname = TestDataLocator.path(
            "join_rule_pathed_role_with_negated_join.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")
        self.assertIsNone(cons)

        expected = [
            "Frequency constraint FrequencyConstraint1 because its join path includes a negated role."
        ]
        self.assertEquals(loader.omissions, expected)

    def test_valid_linear_join_path(self):
        """ Test valid linear join path. """
        fname = TestDataLocator.path("join_rule_valid_linear_path.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")

        self.assertIsNotNone(cons)
        self.assertIsNotNone(cons.covers.join_path)
        self.assertEquals(loader.omissions, [])

        path = cons.covers.join_path
        f1 = model.fact_types.get("AHasB")
        f2 = model.fact_types.get("BHasC")
        f3 = model.fact_types.get("CHasD")

        self.assertEquals(path.fact_types, [f1, f2, f3])
        self.assertEquals(path.joins, [(f1.roles[1], f2.roles[0]),
                                       (f2.roles[1], f3.roles[0])])

    def test_role_path_unexpected_child(self):
        """ Test <RolePath> node with unexpected child node. """
        fname = TestDataLocator.path(
            "join_rule_with_subquery_parameter_inputs.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("FrequencyConstraint1")
        self.assertIsNone(cons)

        expected = ["Frequency constraint FrequencyConstraint1 because its join path has " \
            "a RolePath node with an unsupported child node: SubqueryParameterInputs."]
        self.assertEquals(loader.omissions, expected)

    def test_valid_branching_join_path(self):
        """ Test valid branching join path. """
        fname = TestDataLocator.path("join_rule_valid_branching_path.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("EUC1")

        self.assertIsNotNone(cons)
        self.assertIsNotNone(cons.covers.join_path)
        self.assertEquals(loader.omissions, [])

        path = cons.covers.join_path
        f1 = model.fact_types.get("AHasD")
        f2 = model.fact_types.get("BHasC")
        f3 = model.fact_types.get("CHasD")
        f4 = model.fact_types.get("EHasD")

        self.assertEquals(path.fact_types, [f1, f3, f2, f4])
        self.assertEquals(path.joins, [(f1.roles[1], f3.roles[1]),
                                       (f3.roles[0], f2.roles[1]),
                                       (f1.roles[1], f4.roles[1])])

    def test_valid_complex_branching_join_path(self):
        """ Test valid complex branching join path. """
        fname = TestDataLocator.path(
            "join_rule_valid_complex_branching_path.orm")
        loader = NormaLoader(fname)
        model = loader.model

        cons = model.constraints.get("EUC1")

        self.assertIsNotNone(cons)
        self.assertIsNotNone(cons.covers.join_path)
        self.assertEquals(loader.omissions, [])

        path = cons.covers.join_path
        DHasE = model.fact_types.get("DHasE")
        EHasB = model.fact_types.get("EHasB")
        BHasC = model.fact_types.get("BHasC")
        FHasG = model.fact_types.get("FHasG")
        GHasB = model.fact_types.get("GHasB")
        HHasG = model.fact_types.get("HHasG")

        self.assertEquals(path.fact_types,
                          [DHasE, EHasB, GHasB, FHasG, HHasG, BHasC])
        self.assertEquals(path.joins, [(DHasE.roles[1], EHasB.roles[0]),
                                       (EHasB.roles[1], GHasB.roles[1]),
                                       (GHasB.roles[0], FHasG.roles[1]),
                                       (GHasB.roles[0], HHasG.roles[1]),
                                       (EHasB.roles[1], BHasC.roles[0])])

    def test_load_equality_constraint(self):
        """ Test loading of equality constraint. """
        fname = TestDataLocator.path("equality_four_role.orm")
        loader = NormaLoader(fname)
        model = loader.model

        self.assertItemsEqual(loader.omissions, [])

        cons_list = model.constraints.of_type(Constraint.EqualityConstraint)

        self.assertEquals(3, len(cons_list))

        eq1 = model.constraints.get("EQ")
        eq2 = model.constraints.get("EQ2")
        eq3 = model.constraints.get("EQ3")

        self.assertTrue(isinstance(eq1, Constraint.EqualityConstraint))
        self.assertTrue(isinstance(eq2, Constraint.EqualityConstraint))
        self.assertTrue(isinstance(eq3, Constraint.EqualityConstraint))

        obj = model.object_types.get("A")

        self.assertEquals(eq1.superset, [obj.roles[0]])
        self.assertEquals(eq1.subset, [obj.roles[1]])
        self.assertEquals(eq1.covers, eq1.subset + eq1.superset)

        self.assertEquals(eq2.superset, [obj.roles[0]])
        self.assertEquals(eq2.subset, [obj.roles[2]])
        self.assertEquals(eq2.covers, eq2.subset + eq2.superset)

        self.assertEquals(eq3.superset, [obj.roles[0]])
        self.assertEquals(eq3.subset, [obj.roles[3]])
        self.assertEquals(eq3.covers, eq3.subset + eq3.superset)
コード例 #37
0
    def test_capture_data(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args([])
        c.configure(options, Config())
        c.start()

        def mktest():
            class TC(unittest.TestCase):
                def runTest(self):
                    pass
            test = TC()
            return test
        test = mktest()

        c.beforeTest(test)

        assert hasattr(test, 'logCaptureData')
        eq_(test.logCaptureData.isFinished(), False)
        eq_(test.logCaptureData.getText(), "")

        log = logging.getLogger("foobar.something")
        log.debug("ordinary string log")

        eq_(test.logCaptureData.getText(),
                "foobar.something: DEBUG: ordinary string log")
        eq_(len(test.logCaptureData.getRecords()), 1)
        eq_(test.logCaptureData.isFinished(), False)

        c.afterTest(test)
        
        eq_(test.logCaptureData.isFinished(), True)

        log.debug("NOT PRESENT")

        eq_(test.logCaptureData.getText(),
                "foobar.something: DEBUG: ordinary string log")
        eq_(len(test.logCaptureData.getRecords()), 1)
        eq_(test.logCaptureData._handler, None) # eh. whitebox.

        c.end()
コード例 #38
0
    def test_non_propagating_loggers_handled(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args([])
        c.configure(options, Config())

        logger = logging.getLogger('foo.yes')
        logger.propagate = False

        c.start()
        logger.debug("test message")
        c.end()

        records = c.formatLogRecords()
        eq_(1, len(records))
        assert records[0].startswith('foo.yes:'), records[0]
コード例 #39
0
class TestORMMinusModel(TestCase):
    """ Unit tests for the ORMMinusModel module. """
    def setUp(self):
        self.data_dir = TestDataLocator.get_data_dir()
        self.maxDiff = None

        # Log capturing
        self.log = LogCapture()
        self.log.logformat = '%(levelname)s: %(message)s'
        self.log.begin()

        fname = os.path.join(self.data_dir, "paper_has_author.orm")
        model = NormaLoader(fname).model
        self.paper_has_author = ORMMinusModel(model=model)
        self.solution1 = self.paper_has_author.solution

    def test_overlapping_and_external_iuc(self):
        """ Test that overlapping and external IUCs are ignored. """
        fname = os.path.join(self.data_dir, "overlapping_iuc.orm")
        model = NormaLoader(fname).model

        self.log.beforeTest(None)
        ormminus = ORMMinusModel(model=model)
        solution = ormminus.solution

        actual_vars = [var.name for var in ormminus._variables.itervalues()]

        expected_vars = [
            "ObjectTypes.ValueType1", "ObjectTypes.ValueType2",
            "ObjectTypes.ValueType3",
            "FactTypes.ValueType1HasValueType3HasValueType2",
            "FactTypes.ValueType1HasValueType3HasValueType2.Roles.ValueType1",
            "FactTypes.ValueType1HasValueType3HasValueType2.Roles.ValueType2",
            "FactTypes.ValueType1HasValueType3HasValueType2.Roles.ValueType3",
            "FactTypes.ValueType1HasValueType3",
            "FactTypes.ValueType1HasValueType3.Roles.ValueType1",
            "FactTypes.ValueType1HasValueType3.Roles.ValueType3",
            "FactTypes.ValueType3HasValueType2",
            "FactTypes.ValueType3HasValueType2.Roles.ValueType3",
            "FactTypes.ValueType3HasValueType2.Roles.ValueType2",
            "Constraints.IUC2", "Constraints.IUC3", "Constraints.IUC4"
        ]

        self.assertItemsEqual(actual_vars, expected_vars)

        actual_ignored = [cons.name for cons in ormminus.ignored]
        expect_ignored = ["IUC1", "EUC1"]

        self.assertItemsEqual(actual_ignored, expect_ignored)

        self.assertItemsEqual(self.log.formatLogRecords(), [
            "WARNING: 2 constraints were ignored while checking the model.",
            "INFO: Ignored UniquenessConstraint named IUC1.",
            "INFO: Ignored UniquenessConstraint named EUC1."
        ])

        self.log.afterTest(None)

    def test_disjunctive_mandatory(self):
        """ Test that disjunctive mandatory constraint is ignored. """
        fname = os.path.join(self.data_dir, "disjunctive_mandatory.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model)

        actual = [cons.name for cons in ormminus.ignored]
        expected = ["InclusiveOrConstraint1"]

        self.assertItemsEqual(actual, expected)

    def test_ignored_constraint(self):
        """ Test that appropriate constraints are ignored. """

        # IMPORTANT: I expect this test to fail when I update algorithm to
        # work with subset constraints.  At that point, CHANGE this test to
        # check that a different kind of constraint (e.g. Exclusion) is
        # ignored.  That will require updating NormaLoader to load such
        # constraints rather than omitting them.

        fname = os.path.join(self.data_dir, "subset_constraint.orm")
        model = NormaLoader(fname, deontic=True).model
        ormminus = ORMMinusModel(model=model)
        solution = ormminus.solution

        actual = [cons.name for cons in ormminus.ignored]
        expect = [
            "SubsetConstraint1", "SubsetConstraint2", "SubsetConstraint3",
            "SubsetConstraint4"
        ]
        self.assertItemsEqual(actual, expect)

    def test_ignored_value_constraint(self):
        """ Test that role value constraints are ignored. """
        fname = os.path.join(self.data_dir,
                             "test_value_type_value_constraint.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model)
        solution = ormminus.solution

        actual = [cons.name for cons in ormminus.ignored]
        expect = ["RVC_ET3", "RVC_ET4", "RVC_ET5", "RVC_VT2"]
        self.assertItemsEqual(actual, expect)

    def test_create_variables(self):
        """ Test creation of variables dictionary. """
        actual_vars = [
            var.name for var in self.paper_has_author._variables.itervalues()
        ]
        expect_vars = [
            "ObjectTypes.Paper", "ObjectTypes.Author",
            "FactTypes.PaperHasAuthor", "FactTypes.PaperHasAuthor.Roles.R1",
            "FactTypes.PaperHasAuthor.Roles.R2",
            "Constraints.FrequencyConstraint1",
            "Constraints.InternalUniquenessConstraint1"
        ]

        self.assertItemsEqual(actual_vars, expect_vars)

    def test_create_inequalities_1(self):
        """ Test creation of inequalities for Paper Has Author model. """
        actual = set(
            [ineq.tostring() for ineq in self.paper_has_author._ineqsys])

        expect = [
            "FactTypes.PaperHasAuthor.Roles.R1 <= ObjectTypes.Paper",
            "FactTypes.PaperHasAuthor.Roles.R1 <= FactTypes.PaperHasAuthor",
            "FactTypes.PaperHasAuthor.Roles.R2 <= ObjectTypes.Author",
            "FactTypes.PaperHasAuthor.Roles.R2 <= FactTypes.PaperHasAuthor",
            "ObjectTypes.Paper <= 10", "ObjectTypes.Author <= 5",
            "ObjectTypes.Author <= FactTypes.PaperHasAuthor.Roles.R2",
            "FactTypes.PaperHasAuthor <= 3 * Constraints.FrequencyConstraint1",
            "Constraints.FrequencyConstraint1 <= 0.5 * FactTypes.PaperHasAuthor",
            "Constraints.FrequencyConstraint1 <= FactTypes.PaperHasAuthor.Roles.R1",
            "FactTypes.PaperHasAuthor.Roles.R1 <= Constraints.FrequencyConstraint1",
            "FactTypes.PaperHasAuthor <= Constraints.InternalUniquenessConstraint1",
            "Constraints.InternalUniquenessConstraint1 <= FactTypes.PaperHasAuthor",
            "Constraints.InternalUniquenessConstraint1 <= FactTypes.PaperHasAuthor.Roles.R2",
            "FactTypes.PaperHasAuthor.Roles.R2 <= Constraints.InternalUniquenessConstraint1",
            "ObjectTypes.Paper <= FactTypes.PaperHasAuthor.Roles.R1",
            "FactTypes.PaperHasAuthor <= Constraints.FrequencyConstraint1 * Constraints.InternalUniquenessConstraint1"
        ]

        self.assertItemsEqual(actual, expect)

    def test_solve_1(self):
        """ Test solution to Paper Has Author model. """
        solution = self.solution1
        self.assertEquals(solution["ObjectTypes.Author"], 5)
        self.assertEquals(solution["ObjectTypes.Paper"], 2)
        self.assertEquals(solution["FactTypes.PaperHasAuthor"], 5)
        self.assertEquals(solution["FactTypes.PaperHasAuthor.Roles.R1"], 2)
        self.assertEquals(solution["FactTypes.PaperHasAuthor.Roles.R2"], 5)
        self.assertEquals(solution["Constraints.FrequencyConstraint1"], 2)
        self.assertEquals(
            solution["Constraints.InternalUniquenessConstraint1"], 5)

    def test_implicit_disjunctive_ineq(self):
        """ Test implicit disjunctive mandatory inequalities. """
        self.log.beforeTest(None)
        fname = os.path.join(self.data_dir, "implicit_disjunctive_test.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model)
        solution = ormminus.solution

        actual = set([ineq.tostring() for ineq in ormminus._ineqsys])

        expect = [
            "ObjectTypes.A <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.B <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.C <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.D <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.E <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.F <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "FactTypes.ALikesA.Roles.R1 <= ObjectTypes.A",
            "FactTypes.ALikesA.Roles.R1 <= FactTypes.ALikesA",
            "FactTypes.ALikesA.Roles.R2 <= ObjectTypes.A",
            "FactTypes.ALikesA.Roles.R2 <= FactTypes.ALikesA",
            "FactTypes.ASharesB.Roles.R3 <= ObjectTypes.A",
            "FactTypes.ASharesB.Roles.R3 <= FactTypes.ASharesB",
            "FactTypes.ASharesB.Roles.R4 <= ObjectTypes.B",
            "FactTypes.ASharesB.Roles.R4 <= FactTypes.ASharesB",
            "FactTypes.AOwnsD.Roles.R5 <= ObjectTypes.A",
            "FactTypes.AOwnsD.Roles.R5 <= FactTypes.AOwnsD",
            "FactTypes.AOwnsD.Roles.R6 <= ObjectTypes.D",
            "FactTypes.AOwnsD.Roles.R6 <= FactTypes.AOwnsD",
            "FactTypes.EHasF.Roles.R7 <= ObjectTypes.E",
            "FactTypes.EHasF.Roles.R7 <= FactTypes.EHasF",
            "FactTypes.EHasF.Roles.R8 <= ObjectTypes.F",
            "FactTypes.EHasF.Roles.R8 <= FactTypes.EHasF",
            "FactTypes.ALikesA <= Constraints.IUC1",
            "Constraints.IUC1 <= FactTypes.ALikesA",
            "Constraints.IUC1 <= FactTypes.ALikesA.Roles.R1",
            "FactTypes.ALikesA.Roles.R1 <= Constraints.IUC1",
            "FactTypes.ASharesB <= Constraints.IUC2",
            "Constraints.IUC2 <= FactTypes.ASharesB",
            "Constraints.IUC2 <= FactTypes.ASharesB.Roles.R3",
            "FactTypes.ASharesB.Roles.R3 <= Constraints.IUC2",
            "FactTypes.AOwnsD <= Constraints.IUC3",
            "Constraints.IUC3 <= FactTypes.AOwnsD",
            "Constraints.IUC3 <= FactTypes.AOwnsD.Roles.R5",
            "FactTypes.AOwnsD.Roles.R5 <= Constraints.IUC3",
            "FactTypes.EHasF <= Constraints.IUC4",
            "Constraints.IUC4 <= FactTypes.EHasF",
            "Constraints.IUC4 <= FactTypes.EHasF.Roles.R7",
            "FactTypes.EHasF.Roles.R7 <= Constraints.IUC4",
            "ObjectTypes.A <= FactTypes.ALikesA.Roles.R1 + FactTypes.ALikesA.Roles.R2 + FactTypes.AOwnsD.Roles.R5 + FactTypes.ASharesB.Roles.R3",
            "ObjectTypes.D <= FactTypes.AOwnsD.Roles.R6",
            "ObjectTypes.E <= FactTypes.EHasF.Roles.R7",
            "ObjectTypes.F <= ObjectTypes.D",
            "FactTypes.ALikesA <= Constraints.IUC1 * FactTypes.ALikesA.Roles.R2",
            "FactTypes.ASharesB <= Constraints.IUC2 * FactTypes.ASharesB.Roles.R4",
            "FactTypes.AOwnsD <= Constraints.IUC3 * FactTypes.AOwnsD.Roles.R6",
            "FactTypes.EHasF <= Constraints.IUC4 * FactTypes.EHasF.Roles.R8"
        ]

        self.assertItemsEqual(actual, expect)

        self.assertItemsEqual(self.log.formatLogRecords(), [])
        self.log.afterTest(None)

    def test_implicit_disjunctive_on_entities(self):
        """ Test implicit disjunctive mandatory constraint inequality on
            entity types. """
        fname = os.path.join(self.data_dir, "implicit_disjunctive_test_2.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model)
        solution = ormminus.solution

        actual = set([ineq.tostring() for ineq in ormminus._ineqsys])

        expected = [
            "ObjectTypes.A <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.A_id <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.Boolean <= 2",
            "FactTypes.AHasBoolean.Roles.R1 <= ObjectTypes.A",
            "FactTypes.AHasBoolean.Roles.R1 <= FactTypes.AHasBoolean",
            "FactTypes.AHasBoolean.Roles.R2 <= ObjectTypes.Boolean",
            "FactTypes.AHasBoolean.Roles.R2 <= FactTypes.AHasBoolean",
            "FactTypes.AHasAId.Roles.R1 <= ObjectTypes.A",
            "FactTypes.AHasAId.Roles.R1 <= FactTypes.AHasAId",
            "FactTypes.AHasAId.Roles.R2 <= ObjectTypes.A_id",
            "FactTypes.AHasAId.Roles.R2 <= FactTypes.AHasAId",
            "FactTypes.AHasAId <= Constraints.IUC1",
            "Constraints.IUC1 <= FactTypes.AHasAId",
            "Constraints.IUC1 <= FactTypes.AHasAId.Roles.R2",
            "FactTypes.AHasAId.Roles.R2 <= Constraints.IUC1",
            "FactTypes.AHasAId <= Constraints.IUC2",
            "Constraints.IUC2 <= FactTypes.AHasAId",
            "Constraints.IUC2 <= FactTypes.AHasAId.Roles.R1",
            "FactTypes.AHasAId.Roles.R1 <= Constraints.IUC2",
            "FactTypes.AHasBoolean <= Constraints.IUC3",
            "Constraints.IUC3 <= FactTypes.AHasBoolean",
            "Constraints.IUC3 <= FactTypes.AHasBoolean.Roles.R2",
            "FactTypes.AHasBoolean.Roles.R2 <= Constraints.IUC3",
            "ObjectTypes.A <= FactTypes.AHasAId.Roles.R1",
            "ObjectTypes.A <= FactTypes.AHasBoolean.Roles.R1",
            "ObjectTypes.A_id <= FactTypes.AHasAId.Roles.R2",
            "ObjectTypes.Boolean <= FactTypes.AHasBoolean.Roles.R2",
            "FactTypes.AHasAId <= Constraints.IUC1 * Constraints.IUC2",
            "FactTypes.AHasBoolean <= Constraints.IUC3 * FactTypes.AHasBoolean.Roles.R1"
        ]

        self.assertItemsEqual(actual, expected)

        self.assertEquals(solution["ObjectTypes.A"], 2)

    def test_idmc_with_disjunctive_ref_old_approach(self):
        """ Test implicit disjunctive mandatory constraint inequality when
            entity type has disjunctive ref scheme, using the old approach. """
        fname = os.path.join(self.data_dir, "disjunctive_reference_scheme.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model, experimental=False)

        # Confirm IDMC inequality includes all roles played by A
        actual = set([ineq.tostring() for ineq in ormminus._ineqsys])
        euc = model.constraints.get("EUC")
        a = model.object_types.get("A")

        self.assertIn(
            "ObjectTypes.A <= FactTypes.AHasB.Roles.A + FactTypes.AHasC.Roles.A",
            actual)
        self.assertIsNone(a.identifying_constraint)
        self.assertIsNone(euc.identifier_for)
        self.assertEquals(a.ref_roles, [])

    def test_idmc_with_disjunctive_ref_new_approach(self):
        """ Test implicit disjunctive mandatory constraint inequality when
            entity type has disjunctive ref scheme, using the new approach. """
        fname = os.path.join(self.data_dir, "disjunctive_reference_scheme.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model, experimental=True)

        # Confirm there is *no* IDMC inequality for A because all of its roles
        # are reference roles
        actual = set([
            ineq.tostring() for ineq in ormminus._ineqsys
            if ineq.tostring().startswith("ObjectTypes.A <=")
        ])
        expected = [
            "ObjectTypes.A <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.A <= FactTypes.AHasB.Roles.A",
            "ObjectTypes.A <= FactTypes.AHasC.Roles.A"
        ]

        self.assertItemsEqual(actual, expected)

        # Assert EUC removed and B's role is covered by IUC
        self.assertIsNone(model.constraints.get("EUC"))

        buniq = model.object_types.get("B").roles[0].covered_by[0]
        self.assertTrue(isinstance(buniq, Constraint.UniquenessConstraint))
        self.assertTrue(buniq.simple)

        # Confirm all roles of A are mandatory now
        a = model.object_types.get("A")
        role1 = model.fact_types.get("AHasB").roles[0]
        role2 = model.fact_types.get("AHasC").roles[0]

        self.assertTrue(role1.mandatory)
        self.assertTrue(role2.mandatory)

        # Confirm A's reference roles are intact
        self.assertIs(a.identifying_constraint, None)
        self.assertItemsEqual(a.ref_roles, [role1, role2])

    def test_unsat_smarag_1(self):
        """ Test 1st unsatisfiable model provided by Smaragdakis. """
        fname = os.path.join(self.data_dir, "unsat_smarag_1.orm")
        model = NormaLoader(fname).model
        self.assertIsNone(ORMMinusModel(model=model).solution)

    def test_unsat_smarag_2(self):
        """ Test 2nd unsatisfiable model provided by Smaragdakis. """
        fname = os.path.join(self.data_dir, "unsat_smarag_2.orm")
        model = NormaLoader(fname).model
        self.assertIsNone(ORMMinusModel(model=model).solution)

    def test_unsat_smarag_3(self):
        """ Test 3rd unsatisfiable model provided by Smaragdakis. """
        fname = os.path.join(self.data_dir, "unsat_smarag_3.orm")
        model = NormaLoader(fname).model
        self.assertIsNone(ORMMinusModel(model=model).solution)

    def test_unsat_overlapping_iuc(self):
        """ Test case where OverlappingIFCTransform makes model unsat. """
        fname = os.path.join(self.data_dir,
                             "overlapping_iuc_unsat_if_strengthened.orm")

        model = NormaLoader(fname).model
        self.assertIsNotNone(
            ORMMinusModel(model=model, experimental=False).solution)

        model = NormaLoader(fname).model
        self.assertIsNone(
            ORMMinusModel(model=model, experimental=True).solution)

    def test_unsat_euc_strengthening(self):
        """ Test case where EUC Strengthening makes model unsat. """
        fname = os.path.join(self.data_dir, "euc_strengthening_unsat.orm")

        model = NormaLoader(fname).model
        self.assertIsNotNone(
            ORMMinusModel(model=model, experimental=False).solution)

        model = NormaLoader(fname).model
        self.assertIsNone(
            ORMMinusModel(model=model, experimental=True).solution)

    def test_ubound_on_object_types(self):
        """ Test upper bound on object type variables.  """
        fname = os.path.join(self.data_dir, "data_types.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model, ubound=sys.maxsize)
        solution = ormminus.solution

        bool_obj = model.object_types.get("B")
        bool_var = ormminus._variables[bool_obj]
        self.assertEquals(bool_var.upper, 2)

        int_obj = model.object_types.get("D")
        int_var = ormminus._variables[int_obj]
        self.assertEquals(int_var.upper, sys.maxsize)

        time_obj = model.object_types.get("J")
        time_var = ormminus._variables[time_obj]
        self.assertEquals(time_var.upper, 60 * 24)

    def test_fact_type_parts(self):
        """ Test that fact type parts (e.g. roles vs role sequences) are 
            correctly identified. """
        fname = os.path.join(self.data_dir, "fact_type_parts.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model=model, ubound=5)

        fact_type = model.fact_types.get("V1HasV2HasV3")
        role1, role2, role3 = fact_type.roles
        self.assertItemsEqual(ormminus.get_parts(fact_type),
                              [role1, role2, role3])

        fact_type = model.fact_types.get("V4HasV5")
        role1, role2 = fact_type.roles
        cons = model.constraints.get("IUC4")
        self.assertItemsEqual(ormminus.get_parts(fact_type), [cons, role2])

        fact_type = model.fact_types.get("V6HasV7")
        cons = model.constraints.get("IUC5")
        self.assertItemsEqual(ormminus.get_parts(fact_type), [cons])

        fact_type = model.fact_types.get("V8HasV9")
        cons = model.constraints.get("IFC1")
        self.assertItemsEqual(ormminus.get_parts(fact_type), [cons])

        fact_type = model.fact_types.get("Seven_ary")
        roles = fact_type.roles
        iuc = model.constraints.get("IUC11")
        ifc = model.constraints.get("IFC2")
        self.assertItemsEqual(ormminus.get_parts(fact_type),
                              [iuc, ifc, roles[3], roles[6]])

    def test_cardinality_inequalities(self):
        """ Test that correct cardinality constraint inequalities are generated. """
        self.log.beforeTest(None)
        fname = os.path.join(self.data_dir, "test_cardinality_constraint.orm")
        model = NormaLoader(fname, deontic=True).model
        ormminus = ORMMinusModel(model)

        actual = set([ineq.tostring() for ineq in ormminus._ineqsys])

        expected = [
            "ObjectTypes.A <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "ObjectTypes.B <= " + str(ORMMinusModel.DEFAULT_SIZE),
            "FactTypes.AExists.Roles.A <= ObjectTypes.A",
            "FactTypes.AExists.Roles.A <= FactTypes.AExists",
            "FactTypes.AExists <= Constraints.IUC1",
            "Constraints.IUC1 <= FactTypes.AExists",
            "Constraints.IUC1 <= FactTypes.AExists.Roles.A",
            "FactTypes.AExists.Roles.A <= Constraints.IUC1",
            "ObjectTypes.A <= FactTypes.AExists.Roles.A",
            "FactTypes.BDances.Roles.B <= ObjectTypes.B",
            "FactTypes.BDances.Roles.B <= FactTypes.BDances",
            "FactTypes.BDances <= Constraints.IUC2",
            "Constraints.IUC2 <= FactTypes.BDances",
            "Constraints.IUC2 <= FactTypes.BDances.Roles.B",
            "FactTypes.BDances.Roles.B <= Constraints.IUC2",
            "FactTypes.BHopes.Roles.B <= ObjectTypes.B",
            "FactTypes.BHopes.Roles.B <= FactTypes.BHopes",
            "FactTypes.BHopes <= Constraints.IUC3",
            "Constraints.IUC3 <= FactTypes.BHopes",
            "Constraints.IUC3 <= FactTypes.BHopes.Roles.B",
            "FactTypes.BHopes.Roles.B <= Constraints.IUC3",
            "ObjectTypes.B <= FactTypes.BDances.Roles.B + FactTypes.BHopes.Roles.B",
            "0 <= ObjectTypes.A", "ObjectTypes.A <= 4",
            "4 <= FactTypes.AExists.Roles.A", "FactTypes.AExists.Roles.A <= 7",
            "2 <= ObjectTypes.B", "4 <= FactTypes.BHopes.Roles.B",
            "FactTypes.BHopes.Roles.B <= 4"
        ]
        self.assertItemsEqual(actual, expected)

        self.assertItemsEqual(ormminus.ignored, [model.constraints.get("CC5")])

        self.assertItemsEqual(self.log.formatLogRecords(), [
            "WARNING: 1 constraint was ignored while checking the model.",
            "INFO: Ignored CardinalityConstraint named CC5."
        ])

        self.log.afterTest(None)

    def test_unbounded_freq_constraint(self):
        """ Test a model with an unbounded frequency constraint. """
        fname = os.path.join(self.data_dir,
                             "unbounded_frequency_constraint.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model)

        cons = model.constraints.get("IFC1")
        self.assertEquals(cons.max_freq, float('inf'))
        self.assertEquals(cons.min_freq, 5)

        solution = ormminus.solution
        size = ORMMinusModel.DEFAULT_SIZE
        self.assertEquals(solution["Constraints.IFC1"], size / 5)
        self.assertEquals(solution["FactTypes.AHasB"], size)

    def test_objectification_inequalities(self):
        """ Test a model with objectifications. """
        fname = os.path.join(self.data_dir, "objectification.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=10)

        # Confirm NORMA doesn't copy the cardinality constraint to the fact type
        self.assertEquals(
            len(model.constraints.of_type(Constraint.CardinalityConstraint)),
            1)

        # Check for existence of expected inequalities
        actual = set([ineq.tostring() for ineq in ormminus._ineqsys])
        self.assertIn("ObjectTypes.AHasB <= FactTypes.AHasB", actual)
        self.assertIn("FactTypes.AHasB <= ObjectTypes.AHasB", actual)
        self.assertIn("ObjectTypes.ALikesB <= FactTypes.ALikesB", actual)
        self.assertIn("FactTypes.ALikesB <= ObjectTypes.ALikesB", actual)
        self.assertIn("ObjectTypes.AEnjoysB <= FactTypes.AEnjoysB", actual)
        self.assertIn("FactTypes.AEnjoysB <= ObjectTypes.AEnjoysB", actual)

        # Check that solution has expected relations
        self.assertEquals(ormminus.solution["ObjectTypes.AHasB"],
                          ormminus.solution["FactTypes.AHasB"])
        self.assertEquals(ormminus.solution["ObjectTypes.AHasB"], 10)

        self.assertEquals(ormminus.solution["ObjectTypes.ALikesB"],
                          ormminus.solution["FactTypes.ALikesB"])
        self.assertEquals(ormminus.solution["ObjectTypes.ALikesB"], 5)

        self.assertEquals(ormminus.solution["ObjectTypes.AEnjoysB"],
                          ormminus.solution["FactTypes.AEnjoysB"])
        self.assertEquals(ormminus.solution["ObjectTypes.AEnjoysB"], 3)

    def test_unsat_role_and_value_type_value_constraint(self):
        """ Test unsatisfiable combination of role and value type value constraint. """
        fname = os.path.join(
            self.data_dir,
            "role_value_constraint_and_type_value_constraint.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=10)

        self.assertItemsEqual(ormminus.ignored, [])

        a_id = model.object_types.get("A_id")
        cc1 = model.constraints.get("CC1")
        rvc1 = model.constraints.get("RVC1")
        vc1 = model.constraints.get("VC1")

        value_cons = model.constraints.of_type(Constraint.ValueConstraint)
        self.assertEquals(len(value_cons), 2)

        self.assertItemsEqual(value_cons, [rvc1, vc1])
        self.assertEquals(rvc1.covers, [a_id])
        self.assertEquals(vc1.covers, [a_id])

        self.assertItemsEqual(a_id.covered_by, [rvc1, vc1, cc1])

        # Key test 1: domain of a_id is intersection of two value constraints
        self.assertItemsEqual(a_id.domain.draw(10), [1, 2])

        # Key test 2: model is unsat due to cardinality constraint
        self.assertIsNone(ormminus.solution)

    def test_subtype_inequalities(self):
        """ Test that expected subtype inequalities are created. """
        fname = TestDataLocator.path("value_constraints_on_subtypes.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=30)

        actual = set([ineq.tostring() for ineq in ormminus._ineqsys])

        self.assertIn("ObjectTypes.J <= ObjectTypes.I", actual)
        self.assertIn("ObjectTypes.L <= ObjectTypes.J", actual)
        self.assertIn("ObjectTypes.K <= ObjectTypes.I", actual)
        self.assertIn("ObjectTypes.M <= ObjectTypes.J", actual)
        self.assertIn("ObjectTypes.M <= ObjectTypes.K", actual)

        self.assertEquals(ormminus.solution["ObjectTypes.I"], 21)
        self.assertEquals(ormminus.solution["ObjectTypes.J"], 21)
        self.assertEquals(ormminus.solution["ObjectTypes.K"], 11)
        self.assertEquals(ormminus.solution["ObjectTypes.M"], 11)

    def test_unsat_subtype_with_value_constraint(self):
        """ Test a model that is unsatisfiable because the intersection of the
            value constraints for the root type and subtype is empty. """
        fname = TestDataLocator.path("unsat_subtype_with_value_constraint.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=30)
        self.assertIsNone(ormminus.solution)

    def test_unsat_subtype_due_to_card_constraint(self):
        """ Test a model that is unsatisfiable because the cardinality of the 
            root type is less than required for one of the subtypes. """
        fname = TestDataLocator.path(
            "unsat_subtype_due_to_card_constraint.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=30)
        self.assertIsNone(ormminus.solution)

    def test_sat_with_absorption(self):
        """ Test a satisfiable model with a compound reference scheme. """
        fname = TestDataLocator.path("absorption_valid_simple.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=10)
        self.assertEquals(ormminus.solution["FactTypes.EUC1"], 10)

    def test_unsat_absorption(self):
        """ Test an unsatisfiable model with a compound reference scheme. """
        fname = TestDataLocator.path("absorption_unsat.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=10)
        self.assertIsNone(ormminus.solution)

    def test_unsat_subset(self):
        """ Test a model that is unsatisfiable due to a subset constraint. """
        fname = TestDataLocator.path("subset_unsat.orm")

        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=100, experimental=True)
        self.assertIsNone(ormminus.solution)

        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=100, experimental=False)
        self.assertIsNotNone(ormminus.solution)

    def test_sat_subset(self):
        """ Test a model that is satisfiable with subset constraints. """
        fname = TestDataLocator.path("subset_multiple_roots.orm")
        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=100, experimental=True)
        solution = ormminus.solution

        self.assertIsNotNone(solution)
        self.assertItemsEqual(ormminus.ignored, [])

        self.assertEquals(solution["FactTypes.ALikesB.Roles.A"], 7)
        self.assertEquals(solution["FactTypes.CLikesA.Roles.A"], 7)
        self.assertEquals(solution["FactTypes.ASmokes.Roles.A"], 7)
        self.assertEquals(solution["FactTypes.AExists.Roles.A"], 6)
        self.assertEquals(solution["FactTypes.AHasB.Roles.A"], 6)
        self.assertEquals(solution["ObjectTypes.A"], 7)

        self.assertEquals(solution["FactTypes.ALikesB.Roles.B"], 7)
        self.assertEquals(solution["FactTypes.AHasB.Roles.B"], 6)
        self.assertEquals(solution["ObjectTypes.B"], 7)

        self.assertEquals(solution["ObjectTypes.C"], 100)

        # Check inequalities
        actual = [ineq.tostring() for ineq in ormminus._ineqsys]

        # Check IDMC for A
        filt = lambda x: x.startswith("ObjectTypes.A <=")
        self.assertItemsEqual(filter(filt, actual), [
            "ObjectTypes.A <= 100",
            "ObjectTypes.A <= FactTypes.ALikesB.Roles.A"
        ])

        # Check IDMC for B
        filt = lambda x: x.startswith("ObjectTypes.B <=")
        self.assertItemsEqual(filter(filt, actual), [
            "ObjectTypes.B <= 100", "ObjectTypes.B <= 7",
            "ObjectTypes.B <= FactTypes.ALikesB.Roles.B + FactTypes.BExists.Roles.B"
        ])

        # Confirm R < S inequalities present
        self.assertIn("FactTypes.AHasB.Roles.A <= FactTypes.ALikesB.Roles.A",
                      actual)
        self.assertIn("FactTypes.AHasB.Roles.B <= FactTypes.ALikesB.Roles.B",
                      actual)

    def test_ignored_subset(self):
        """ Test a model with an ignored subset constraint. """
        fname = TestDataLocator.path("subset_with_incompat_superset.orm")
        model = NormaLoader(fname).model

        subset = model.constraints.get("SUB1")

        ormminus = ORMMinusModel(model, ubound=100, experimental=True)
        solution = ormminus.solution

        self.assertIsNotNone(solution)
        self.assertItemsEqual(ormminus.ignored, [subset])

    def test_unsat_equality(self):
        """ Test a model that is unsatisfiable due to an equality constraint. """
        fname = TestDataLocator.path("equality_unsat.orm")

        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=100, experimental=True)
        self.assertIsNone(ormminus.solution)

        actual = [ineq.tostring() for ineq in ormminus._ineqsys]

        self.assertIn("FactTypes.ALovesB.Roles.A <= FactTypes.AHasB.Roles.A",
                      actual)
        self.assertIn("FactTypes.AHasB.Roles.A <= FactTypes.ALovesB.Roles.A",
                      actual)

        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=100, experimental=False)
        self.assertIsNotNone(ormminus.solution)

    def test_unsat_join_equality(self):
        """ Test a model that is unsatisfiable due to a join equality constraint. """
        fname = TestDataLocator.path("join_equality_unsat.orm")

        model = NormaLoader(fname).model
        ormminus = ORMMinusModel(model, ubound=100, experimental=True)

        self.assertEquals(ormminus.ignored, [])
        self.assertIsNone(ormminus.solution)

        model = NormaLoader(fname).model
        eq = model.constraints.get("EQ")
        ormminus = ORMMinusModel(model, ubound=100, experimental=False)

        self.assertEquals(ormminus.ignored, [eq])
        self.assertIsNotNone(ormminus.solution)
コード例 #40
0
 def test_logging_filter_exclude(self):
     env = {'NOSE_LOGFILTER': '-foo,-bar'}
     c = LogCapture()
     parser = OptionParser()
     c.addOptions(parser, env)
     options, args = parser.parse_args(['foo'])
     print options, args
     c.configure(options, Config())
     c.start()
     for name in ['foobar.something', 'foo', 'foo.x', 'abara', 'bar.quux']:
         log = logging.getLogger(name)
         log.info("Hello %s" % name)
     c.end()
     records = c.formatLogRecords()
     eq_(2, len(records))
     assert records[0].startswith('foobar.something:'), records[0]
     assert records[1].startswith('abara:'), records[1]
コード例 #41
0
    def test_clears_all_existing_log_handlers(self):
        c = LogCapture()
        parser = OptionParser()
        c.addOptions(parser, {})
        options, args = parser.parse_args(['--logging-clear-handlers'])
        c.configure(options, Config())
        eq_(c.clear, True)

        def mktest():
            class TC(unittest.TestCase):
                def runTest(self):
                    pass

            test = TC()
            return test

        logging.getLogger().addHandler(StreamHandler(sys.stdout))
        log = logging.getLogger("dummy")
        log.addHandler(StreamHandler(sys.stdout))

        c.start()
        c.beforeTest(mktest())
        c.end()

        if py27:
            expect = ["<class 'nose.plugins.logcapture.MyMemoryHandler'>"]
        else:
            expect = ['nose.plugins.logcapture.MyMemoryHandler']
        eq_([str(c.__class__) for c in logging.getLogger().handlers], expect)
        eq_([str(c.__class__) for c in logging.getLogger("dummy").handlers],
            [])
コード例 #42
0
 def test_enabled_by_default(self):
     c = LogCapture()
     assert c.enabled