import datetime
import os
import tempfile
import time
import unittest

from miro import schema
from miro.schema import (SchemaString, SchemaInt, SchemaFloat, SchemaBool,
                         SchemaDateTime, SchemaList, SchemaDict, SchemaObject,
                         SchemaReprContainer, ValidationError)
from miro.test.framework import MiroTestCase

class TestValidation(MiroTestCase):
    def test_module_variables_defined(self):
        self.assert_(hasattr(schema, 'VERSION'))
        self.assert_(hasattr(schema, 'object_schemas'))

    def test_none_validation(self):
        self.assertRaises(ValidationError, SchemaInt(noneOk=False).validate,
                          None)
        self.assertRaises(ValidationError, SchemaInt().validate, None)
        SchemaInt(noneOk=True).validate(None)

    def test_bool_validation(self):
        schemabool = SchemaBool()
        self.assertRaises(ValidationError, schemabool.validate, 1)
        self.assertRaises(ValidationError, schemabool.validate, 0)
        self.assertRaises(ValidationError, schemabool.validate, "True")
        self.assertRaises(ValidationError, schemabool.validate, None)
        schemabool.validate(True)
        schemabool.validate(False)

    def test_date_time_validation(self):
        schemadatetime = SchemaDateTime()
        self.assertRaises(ValidationError, schemadatetime.validate, 1)
        self.assertRaises(ValidationError, schemadatetime.validate, 0)
        delta = datetime.timedelta(days=40)
        self.assertRaises(ValidationError, schemadatetime.validate, delta)
        schemadatetime.validate(datetime.datetime(1980, 8, 1))

    def test_int_validation(self):
        schemaint = SchemaInt()
        self.assertRaises(ValidationError, schemaint.validate, "One")
        self.assertRaises(ValidationError, schemaint.validate, 1.4)
        schemaint.validate(1)
        schemaint.validate(1L)

    def test_float_validation(self):
        schemafloat = SchemaFloat()
        self.assertRaises(ValidationError, schemafloat.validate, "One half")
        self.assertRaises(ValidationError, schemafloat.validate, 1)
        schemafloat.validate(1.4)

    def test_string_validation(self):
        schemastring = SchemaString()
        self.assertRaises(ValidationError, schemastring.validate, 10123)
        self.assertRaises(ValidationError, schemastring.validate, "10123")
        schemastring.validate(u"10123")

    def test_repr_container_validatoin(self):
        schemasimple = SchemaReprContainer()
        schemasimple.validate({1: u"Ben", u"pie": 3.1415})
        schemasimple.validate([1, 1, u"two", u"three", 5])
        schemasimple.validate({u'y2k': datetime.datetime(2000, 1, 1),
                               'now': time.localtime()})
        schemasimple.validate({
            'fib': (1, 1, u"two", u"three", 5),
            'square': (1, 4, u"nine", 16),
            'fact': (1, 2.0, 6, u"twenty-four"),
            })
        # make sure circular references doesn't screw it up
        l = []
        d = {}
        l.extend([l, d])
        d['list'] = l
        schemasimple.validate(l)
        schemasimple.validate(d)

        class TestObject(object):
            pass
        self.assertRaises(ValidationError, schemasimple.validate,
                          TestObject())
        self.assertRaises(ValidationError, schemasimple.validate,
                          [TestObject()])
        self.assertRaises(ValidationError, schemasimple.validate, 
                          {'object': TestObject()})

    def test_list_validation(self):
        schemalist = SchemaList(SchemaInt())
        self.assertRaises(ValidationError, schemalist.validate,
                          1234)
        schemalist.validate([1, 2, 3, 4])

    def test_dict_validation(self):
        schemadict = SchemaDict(SchemaInt(), SchemaString())
        self.assertRaises(ValidationError, schemadict.validate,
                1234)
        schemadict.validate({12: u"Buckle my shoe"})

    def test_object_validation(self):
        class TestObject(object):
            pass
        class ChildObject(TestObject):
            pass

        schemaobject = SchemaObject(TestObject)
        self.assertRaises(ValidationError, schemaobject.validate, 1234)
        schemaobject.validate(TestObject())
        # child objects should work
        schemaobject.validate(ChildObject())
        # the actual class object shouldn't
        self.assertRaises(ValidationError, schemaobject.validate, TestObject)

if __name__ == '__main__':
    unittest.main()
