# Copyright (C) 2009, Tutorius.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import unittest import uuid import os import copy from sugar.tutorius.constraints import * from sugar.tutorius.properties import * # Helper function to test the wrong types on a property, given its type def try_wrong_values(obj): typ = type(obj).prop.type if typ != "int": try: obj.prop = 3 assert False, "Able to insert int value in property of type %s"%typ except: pass if typ != "float": try: obj.prop = 1.1 assert False, "Able to insert float value in property of type %s"%typ except: pass if typ != "string": try: obj.prop = "Fake string" assert False, "Able to insert string value in property of type %s"%typ except: pass if typ != "array": try: obj.prop = [1, 2000, 3, 400] assert False, "Able to insert array value in property of type %s"%typ except: pass if typ != "color": try: obj.prop = [1,2,3] if typ != "array": assert False, "Able to insert color value in property of type %s"%typ except: pass if typ != "boolean": try: obj.prop = True if typ != "boolean": assert False, "Able to set boolean value in property of type %s"%typ except: pass class BasePropertyTest(unittest.TestCase): def test_base_class(self): class klass(TPropContainer): prop = TutoriusProperty() obj = klass() assert klass.prop.default == None, "There should not be an initial value in the base property" assert klass.prop.type == None, "There should be no type associated with the base property" assert klass.prop.get_constraints() == [], "There should be no constraints on the base property" obj.prop = 2 assert obj.prop == 2, "Unable to set a value on base class" def test_eq_(self): class klass(TPropContainer): prop = TutoriusProperty() obj = klass() obj2 = klass() assert obj == obj2, "Base property containers should be identical" class AdvancedPropertyTest(unittest.TestCase): def test_properties_groups(self): """ Tests complex properties containers for identity. """ class klass1(TPropContainer): message = TutoriusProperty() property = TutoriusProperty() data = TutoriusProperty() class klass3(TPropContainer): property = TutoriusProperty() message = TutoriusProperty() data = TutoriusProperty() extra_prop = TutoriusProperty() class klass4(TPropContainer): property = TutoriusProperty() message = TutoriusProperty() data = TFloatProperty(13.0) obj1 = klass1() obj1.property = 12 obj1.message = "Initial message" obj1.data = [132, 208, 193, 142] obj2 = klass1() obj2.property = 12 obj2.message = "Initial message" obj2.data = [132, 208, 193, 142] obj3 = klass3() obj3.property = 12 obj3.message = "Initial message" obj3.data = [132, 208, 193, 142] obj3.extra_prop = "Suprprise!" obj4 = klass4() obj4.property = 12 obj4.message = "Initial message" obj4.data = 13.4 # Ensure that both obj1 and obj2 are identical (they have the same list of # properties and they have the same values assert obj1 == obj1, "Identical objects were considered as different" # Ensure that obj1 is different from obj3, since obj3 has an extra property assert not (obj1 == obj3), "Objects should not be identical since obj3 has more props" assert not (obj3 == obj1), "Objects should not be identical since obj3 has more properties" # Ensure that properties of different type are considered as different assert not (obj1 == obj4), "Properties of different type should not be equal" def test_addon_properties(self): """Test an addon property. This tests creates a class with a single addon property (klass1) and assigns a new addon to it (inner1).""" class klass1(TPropContainer): addon = TAddonProperty() class inner1(TPropContainer): internal = TutoriusProperty() def __init__(self, value): TPropContainer.__init__(self) self.internal = value obj1 = klass1() obj1.addon = inner1("Hi!") obj2 = klass1() obj2.addon = inner1("Hi!") assert obj1 == obj2, "Identical objects with addon properties were treated as different" obj3 = klass1() obj3.addon = inner1("Hello!") assert not (obj1 == obj3), "Objects with addon property having a different value should be considered different" def test_addonlist_properties(self): class klass1(TPropContainer): addon_list = TAddonListProperty() class inner1(TPropContainer): message = TutoriusProperty() data = TutoriusProperty() def __init__(self, message, data): TPropContainer.__init__(self) self.message = message self.data = data class inner2(TPropContainer): message = TutoriusProperty() other_data = TutoriusProperty() def __init__(self, message, data): TPropContainer.__init__(self) self.message = message self.other_data = data obj1 = klass1() obj1.addon_list = [inner1('Hi!', 12), inner1('Hello.', [1,2])] obj2 = klass1() obj2.addon_list = [inner1('Hi!', 12), inner1('Hello.', [1,2])] assert obj1 == obj2, "Addon lists with the same containers were considered different" obj3 = klass1() obj3.addon_list = [inner1('Hi!', 12), inner2('Hello.', [1,2])] assert not (obj1 == obj3), "Differently named properties should be considered different in the addon list tests" class TIntPropertyTest(unittest.TestCase): def test_int_property(self): class klass(TPropContainer): prop = TIntProperty(22) obj = klass() assert obj.prop == 22, "Could not set value on property via constructor" assert klass.prop.type == "int", "Wrong type on int property : %s" % prop.type cons = klass.prop.get_constraints() assert len(cons) == 2, "Not enough constraints on the int property" obj.prop = 12 assert obj.prop == 12, "Could not set value" def test_wrong_values(self): class klass(TPropContainer): prop = TIntProperty(33) obj = klass() # Try setting values of other types try_wrong_values(obj) def test_limit_constructor(self): class klass(TPropContainer): prop = TIntProperty(22, 0, 30) obj = klass() try: obj.prop = -22 assert False, "Assigning an out-of-range value should trigger LowerLimitConstraint" except LowerLimitConstraintError: pass except Exception: assert False, "Wrong exception triggered by assignation" try: obj.prop = 222 assert False, "Assigning an out-of-range value should trigger UpperLimitConstraint" except UpperLimitConstraintError: pass except Exception: assert False, "Wrong exception triggered by assignation" def test_failing_constructor(self): try: prop = TIntProperty(100, 0, 20) assert False, "Creation of the property should fail." except UpperLimitConstraintError: pass except: assert False, "Wrong exception type on failed constructor" try: prop = TIntProperty(-100, 0, 20) assert False, "Creation of the property should fail." except LowerLimitConstraintError: pass except: assert False, "Wrong exception type on failed constructor" class TFloatPropertyTest(unittest.TestCase): def test_float_property(self): class klass(TPropContainer): prop = TFloatProperty(22) obj = klass() assert obj.prop == 22, "Could not set value on property via constructor" assert klass.prop.type == "float", "Wrong type on float property : %s" % klass.prop.type cons = klass.prop.get_constraints() assert len(cons) == 2, "Not enough constraints on the float property" obj.prop = 12 assert obj.prop == 12, "Could not set value" def test_wrong_values(self): class klass(TPropContainer): prop = TFloatProperty(33) obj = klass() # Try setting values of other types try_wrong_values(obj) def test_limit_constructor(self): class klass(TPropContainer): prop = TFloatProperty(22.4, 0.1, 30.5223) obj = klass() try: obj.prop = -22.8 assert False, "Assigning an out-of-range value should trigger LowerLimitConstraint" except LowerLimitConstraintError: pass except Exception: assert False, "Wrong exception triggered by assignation" try: obj.prop = 222.2 assert False, "Assigning an out-of-range value should trigger UpperLimitConstraint" except UpperLimitConstraintError: pass except Exception: assert False, "Wrong exception triggered by assignation" def test_failing_constructor(self): try: prop = TFloatProperty(100, 0, 20) assert False, "Creation of the property should fail." except UpperLimitConstraintError: pass except: assert False, "Wrong exception type on failed constructor" try: prop = TFloatProperty(-100, 0, 20) assert False, "Creation of the property should fail." except LowerLimitConstraintError: pass except: assert False, "Wrong exception type on failed constructor" class TStringPropertyTest(unittest.TestCase): def test_basic_string(self): class klass(TPropContainer): prop = TStringProperty("Starter string") obj = klass() assert obj.prop == "Starter string", "Could not set string value via constructor" assert klass.prop.type == "string", "Wrong type for string property : %s" % klass.prop.type def test_size_limit(self): class klass(TPropContainer): prop = TStringProperty("Small", 10) obj = klass() try: obj.prop = "My string is too big!" assert False, "String should not set to longer than max size" except MaxSizeConstraintError: pass except: assert False, "Wrong exception type thrown" def test_wrong_values(self): class klass(TPropContainer): prop = TStringProperty("Beginning") obj = klass() try_wrong_values(obj) def test_failing_constructor(self): try: prop = TStringProperty("This is normal", 5) assert False, "Creation of the property should fail." except MaxSizeConstraintError: pass except: assert False, "Wrong exception type on failed constructor" class TArrayPropertyTest(unittest.TestCase): def test_basic_array(self): class klass(TPropContainer): prop = TArrayProperty([1, 2, 3, 4]) obj = klass() assert obj.prop == (1,2,3,4), "Unable to set initial value via constructor" assert klass.prop.type == "array", "Wrong type for array : %s"%klass.prop.type def test_wrong_values(self): class klass(TPropContainer): prop = TArrayProperty([1,2,3,4,5]) obj = klass() try_wrong_values(obj) def test_size_limits(self): class klass(TPropContainer): prop = TArrayProperty([1,2], None, 4) obj = klass() try: obj.prop = [1,2,4,5,6,7] assert False, "Maximum size limit constraint was not properly applied" except MaxSizeConstraintError: pass class klass(TPropContainer): prop = TArrayProperty([1,2,3,4], 2) obj = klass() try: obj.prop = [1] assert False, "Minimum size limit constraint was not properly applied" except MinSizeConstraintError: pass def test_failing_constructor(self): try: prop = TArrayProperty([100, 0, 20], None, 2) assert False, "Creation of the property should fail." except MaxSizeConstraintError: pass try: prop = TArrayProperty([100, 0, 20], 4, None) assert False, "Creation of the property should fail." except MinSizeConstraintError: pass class TColorPropertyTest(unittest.TestCase): def test_basic_color(self): class klass(TPropContainer): prop = TColorProperty(20, 40, 60) obj = klass() assert obj.prop == [20, 40, 60], "Could not set initial value with constructor" assert klass.prop.type == "color", "Wrong type on color : %s"%klass.prop.type def test_wrong_values(self): class klass(TPropContainer): prop = TColorProperty(250, 250, 250) obj = klass() try_wrong_values(obj) def test_failing_constructor(self): try: prop = TColorProperty(0, "str", 0) assert False, "Creation of the property should fail." except ColorTypeError: pass except: assert False, "Wrong exception type on failed constructor" class TBooleanPropertyTest(unittest.TestCase): def setUp(self): class klass(TPropContainer): prop = TBooleanProperty(False) self.obj = klass() def test_basic_boolean(self): assert self.obj.prop == False, "Could not set initial value via constructor" assert self.obj.__class__.prop.type == "boolean", "Wrong type for TBooleanProperty : %s"%self.obj.__class__.prop.type self.obj.prop = True assert self.obj.prop == True, "Could not change the value via set" self.obj.prop = False assert self.obj.prop == False, "Could not change the value via set" def test_wrong_types(self): try_wrong_values(self.obj) def test_failing_constructor(self): try: prop = TBooleanProperty(64) assert False, "Creation of the property should fail with non-boolean value" except BooleanConstraintError: pass except: assert False, "Wrong exception type on failed constructor" class TEnumPropertyTest(unittest.TestCase): def setUp(self): class klass(TPropContainer): prop = TEnumProperty("hello", [1, 2, "hello", "world", True, None]) self.obj = klass() def test_basic_enum(self): assert self.obj.prop == "hello", "Could not set initial value on property" assert type(self.obj).prop.type == "enum", "Wrong type for TEnumProperty : %s"%type(self.obj).prop.type self.obj.prop = True assert self.obj.prop, "Could not change the value via set" try: self.obj.prop = 4 assert False, "Switched to a value outside the enum" except EnumConstraintError: pass def test_wrong_type(self): try_wrong_values(self.obj) class TFilePropertyTest(unittest.TestCase): root_folder = "/tmp/tutorius" def setUp(self): try: os.mkdir(self.root_folder) except: pass # Create some sample, unique files for the tests self.temp_filename1 = os.path.join(self.root_folder, "sample_file1_" + str(uuid.uuid1()) + ".txt") self.temp_file1 = file(self.temp_filename1, "w") self.temp_file1.close() self.temp_filename2 = os.path.join(self.root_folder, "sample_file2_" + str(uuid.uuid1()) + ".txt") self.temp_file2 = file(self.temp_filename2, "w") self.temp_file2.close() class klass(TPropContainer): prop = TFileProperty(self.temp_filename1) self.obj = klass() def tearDown(self): # Unlink the files from the disk when tests are over os.unlink(self.temp_filename1) os.unlink(self.temp_filename2) def test_basic_file(self): assert self.obj.prop == self.temp_filename1, "Could not set initial value" assert type(self.obj).prop.type == "file", "Wrong type for TFileProperty : %s"%type(self.obj).prop.type self.obj.prop = self.temp_filename2 assert self.obj.prop == self.temp_filename2, "Could not change value" try: self.obj.prop = "unknown/file/on/disk.gif" assert False, "An exception should be thrown on unknown file" except FileConstraintError: pass class TResourcePropertyTest(unittest.TestCase): def test_valid_names(self): class klass1(TPropContainer): res = TResourceProperty() name1 = "file_" + unicode(uuid.uuid1()) + ".png" name2 = unicode(uuid.uuid1()) + "_" + unicode(uuid.uuid1()) + ".extension" name3 = "/home/user/.sugar/_random/new_image1231_" + unicode(uuid.uuid1()).upper() + ".mp3" name4 = "a_" + unicode(uuid.uuid1()) name5 = "" obj1 = klass1() obj1.res = name1 assert obj1.res == name1, "Could not assign the valid name correctly : %s" % name1 obj1.res = name2 assert obj1.res == name2, "Could not assign the valid name correctly : %s" % name2 obj1.res = name3 assert obj1.res == name3, "Could not assign the valid name correctly : %s" % name3 obj1.res = name4 assert obj1.res == name4, "Could not assign the valid name correctly : %s" % name4 obj1.res = name5 assert obj1.res == name5, "Could not assign the valid name correctly : %s" % name5 def test_invalid_names(self): class klass1(TPropContainer): res = TResourceProperty() bad_name1 = ".jpg" bad_name2 = "_.jpg" bad_name3 = "_" + unicode(uuid.uuid1()) obj1 = klass1() try: obj1.res = bad_name1 assert False, "A invalid name was accepted : %s" % bad_name1 except ResourceConstraintError: pass try: obj1.res = bad_name2 assert False, "A invalid name was accepted : %s" % bad_name2 except ResourceConstraintError: pass try: obj1.res = bad_name3 assert False, "A invalid name was accepted : %s" % bad_name3 except ResourceConstraintError: pass class TAddonPropertyTest(unittest.TestCase): def test_wrong_value(self): class klass1(TPropContainer): addon = TAddonProperty() class wrongAddon(object): pass obj1 = klass1() obj1.addon = klass1() try: obj1.addon = wrongAddon() assert False, "Addon Property should not accept non-TPropContainer values" except ValueError: pass class TAddonPropertyList(unittest.TestCase): def test_wrong_value(self): class klass1(TPropContainer): addonlist = TAddonListProperty() class wrongAddon(object): pass obj1 = klass1() obj1.addonlist = [klass1(), klass1()] try: obj1.addonlist = klass1() assert False, "TAddonPropeprty shouldn't accept anything else than a list" except ValueError: pass try: obj1.addonlist = [klass1(), klass1(), wrongAddon(), klass1()] except ValueError: pass if __name__ == "__main__": unittest.main()