"""Unit tests for models and capabilities"""

import unittest

class ModelsTestCase(unittest.TestCase):
    """Unit tests for the sciunit module"""

    def setUp(self):
        from sciunit.models.examples import UniformModel
        self.M = UniformModel
        
    def test_curr_method(self):
        from sciunit import Model
        class TestModel(Model):
            def test_calling_curr_method(self):
                return self.curr_method()
        m = TestModel()
        test_method_name = m.test_calling_curr_method()
        self.assertEqual(test_method_name, "test_calling_curr_method")

    def test_failed_extra_capabilities(self):
        from sciunit import Model

        class TestModel(Model):
            def test_return_none_function(self):
                return None
        
        m = TestModel()
        m.extra_capability_checks = {TestModel : "test_return_none_function"}
        test_list = m.failed_extra_capabilities

        self.assertEqual(test_list[0], TestModel)
        self.assertEqual(len(test_list), 1)

    def test_get_model_state(self):
        from sciunit import Model

        m = Model()
        state = m.__getstate__()
        self.assertEqual(m.__dict__, state)

    def test_get_model_capabilities(self):
        from sciunit.capabilities import ProducesNumber

        m = self.M(2, 3)
        self.assertEqual(m.capabilities, [ProducesNumber])

    def test_get_model_description(self):
        m = self.M(2, 3)
        m.describe()
        m.description = "Lorem Ipsum"
        m.describe()

    def test_check_model_capabilities(self):
        from sciunit.tests import RangeTest
        t = RangeTest([2,3])
        m = self.M(2,3)
        t.check(m)
        
    def test_check_missing_capabilities_1(self):
        from sciunit.capabilities import Runnable
        from sciunit.errors import CapabilityNotImplementedError
        
        m = self.M(2, 3, name='Not actually runnable due to lack of capability provision')
        try:
            m.run()
        except AttributeError as e:
            pass
        else:
            self.fail("Unprovided capability was called and not caught")
    
    def test_check_missing_capabilities_2(self):
        from sciunit.capabilities import Runnable
        from sciunit.errors import CapabilityNotImplementedError
        
        class MyModel(self.M, Runnable):
            pass
        
        m = MyModel(2, 3, name='Not actually runnable due to lack of capability implementation')
        try:
            m.run()
        except CapabilityNotImplementedError as e:
            pass
        else:
            self.fail("Unimplemented capability was called and not caught")
        
    def test_check_missing_capabilities_3(self):
        from sciunit.capabilities import Runnable
        from sciunit.errors import CapabilityNotImplementedError
        
        class MyModel(self.M, Runnable):
            def run(self):
                print("Actually running!")
        
        m = MyModel(2, 3, name='Now actually runnable')
        m.run()
        
    def test_regular_models(self):
        from sciunit.models.examples\
            import ConstModel, UniformModel, SharedModel, PersistentUniformModel

        m = ConstModel(3)
        self.assertEqual(m.produce_number(),3)

        m = UniformModel(3,4)
        self.assertTrue(3 < m.produce_number() < 4)

        m = PersistentUniformModel(3, 4)
        m.run()
        self.assertTrue(3 < m.produce_number() < 4)

    def test_irregular_models(self):
        from sciunit.models.examples\
            import CacheByInstancePersistentUniformModel,\
            CacheByValuePersistentUniformModel

        a = CacheByInstancePersistentUniformModel(2,3)
        a1 = a.produce_number()
        a2 = a.produce_number()
        self.assertEqual(a1,a2)
        b = CacheByInstancePersistentUniformModel(2,3)
        b1 = b.produce_number()
        self.assertNotEqual(b1,a2)

        c = CacheByValuePersistentUniformModel(2,3)
        c1 = c.produce_number()
        c2 = c.produce_number()
        self.assertEqual(c1,c2)
        d = CacheByValuePersistentUniformModel(2,3)
        d1 = d.produce_number()
        self.assertEqual(d1,c2)
        


class CapabilitiesTestCase(unittest.TestCase):
    """Unit tests for sciunit Capability classes"""

    def test_capabilities(self):
        from sciunit import Model
        from sciunit.capabilities import ProducesNumber
        from sciunit.models import Model
        from sciunit.models.examples import UniqueRandomNumberModel,\
            RepeatedRandomNumberModel

        class MyModel(Model,ProducesNumber):
            def produce_number(self):
                return 3.14
        m = MyModel()
        self.assertEqual(m.produce_number(),3.14)

        m = UniqueRandomNumberModel()
        self.assertNotEqual(m.produce_number(),m.produce_number())

        m = RepeatedRandomNumberModel()
        self.assertEqual(m.produce_number(),m.produce_number())

if __name__ == '__main__':
    unittest.main()
@@ -250,28 +250,163 @@
 rmModel%0A    
+%0A
     
+def test_getattr(self):%0A        from sciunit import Model%0A        m = Model()%0A        self.assertEqual(m.name, m.__getattr__(%22name%22))%0A
 %0A    def tes

Add test_getattr