Andreas Raab uploaded a new version of TraitsTests to project The Trunk:
http://source.squeak.org/trunk/TraitsTests-ar.1.mcz ==================== Summary ==================== Name: TraitsTests-ar.1 Author: ar Time: 31 December 2009, 3:57:32 am UUID: e4d14d09-2f43-1e44-b244-ed76a3641e1e Ancestors: Put traits tests back as separate package. ==================== Snapshot ==================== SystemOrganization addCategory: #'TraitsTests-Kernel'! TestResource subclass: #TraitsResource instanceVariableNames: 'createdClassesAndTraits t1 t2 t3 t4 t5 t6 c1 c2 c3 c4 c5 c6 c7 c8 dirty' classVariableNames: 'SetUpCount' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: TraitsResource class>>resetIfDirty (in category 'as yet unclassified') ----- resetIfDirty self current isDirty ifTrue: [self reset]! ----- Method: TraitsResource>>c1 (in category 'accessing') ----- c1 ^c1! ----- Method: TraitsResource>>c1: (in category 'accessing') ----- c1: anObject ^c1 := anObject! ----- Method: TraitsResource>>c2 (in category 'accessing') ----- c2 ^c2! ----- Method: TraitsResource>>c2: (in category 'accessing') ----- c2: anObject ^c2 := anObject! ----- Method: TraitsResource>>c3 (in category 'accessing') ----- c3 ^c3! ----- Method: TraitsResource>>c3: (in category 'accessing') ----- c3: anObject ^c3 := anObject! ----- Method: TraitsResource>>c4 (in category 'accessing') ----- c4 ^c4! ----- Method: TraitsResource>>c4: (in category 'accessing') ----- c4: anObject ^c4 := anObject! ----- Method: TraitsResource>>c5 (in category 'accessing') ----- c5 ^c5! ----- Method: TraitsResource>>c5: (in category 'accessing') ----- c5: anObject ^c5 := anObject! ----- Method: TraitsResource>>c6 (in category 'accessing') ----- c6 ^c6! ----- Method: TraitsResource>>c6: (in category 'accessing') ----- c6: anObject ^c6 := anObject! ----- Method: TraitsResource>>c7 (in category 'accessing') ----- c7 ^c7! ----- Method: TraitsResource>>c7: (in category 'accessing') ----- c7: anObject ^c7 := anObject! ----- Method: TraitsResource>>c8 (in category 'accessing') ----- c8 ^c8! ----- Method: TraitsResource>>c8: (in category 'accessing') ----- c8: anObject ^c8 := anObject! ----- Method: TraitsResource>>categoryName (in category 'as yet unclassified') ----- categoryName ^self class category! ----- Method: TraitsResource>>codeChangedEvent: (in category 'as yet unclassified') ----- codeChangedEvent: anEvent (anEvent isDoIt not and: [anEvent itemClass notNil] and: [self createdClassesAndTraits includes: anEvent itemClass instanceSide]) ifTrue: [self setDirty] ! ----- Method: TraitsResource>>createClassNamed:superclass:uses: (in category 'as yet unclassified') ----- createClassNamed: aSymbol superclass: aClass uses: aTraitComposition | class | class := aClass subclass: aSymbol uses: aTraitComposition instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: self categoryName. self createdClassesAndTraits add: class. ^class! ----- Method: TraitsResource>>createTraitNamed:uses: (in category 'as yet unclassified') ----- createTraitNamed: aSymbol uses: aTraitComposition | trait | trait := Trait named: aSymbol uses: aTraitComposition category: self categoryName env: Smalltalk. self createdClassesAndTraits add: trait. ^trait! ----- Method: TraitsResource>>createdClassesAndTraits (in category 'as yet unclassified') ----- createdClassesAndTraits createdClassesAndTraits ifNil: [ createdClassesAndTraits := OrderedCollection new]. ^createdClassesAndTraits! ----- Method: TraitsResource>>isDirty (in category 'accessing') ----- isDirty ^dirty! ----- Method: TraitsResource>>setDirty (in category 'accessing') ----- setDirty dirty := true! ----- Method: TraitsResource>>setUp (in category 'as yet unclassified') ----- setUp "Please note, that most tests rely on this setup of traits and classes - and that especially the order of the definitions matters." "SetUpCount := SetUpCount + 1." dirty := false. SystemChangeNotifier uniqueInstance doSilently: [self t1: (self createTraitNamed: #T1 uses: { }). self t1 comment: 'I am the trait T1'. self t2: (self createTraitNamed: #T2 uses: { }). self t2 compile: 'm21 ^21' classified: #cat1. self t2 compile: 'm22 ^22' classified: #cat2. self t2 classSide compile: 'm2ClassSide: a ^a'. self t3: (self createTraitNamed: #T3 uses: { }). self t3 compile: 'm31 ^31' classified: #cat1. self t3 compile: 'm32 ^32' classified: #cat2. self t3 compile: 'm33 ^33' classified: #cat3. self t4: (self createTraitNamed: #T4 uses: { (self t1). (self t2) }). self t4 compile: 'm11 ^41' classified: #catX. "overrides T1>>m11" self t4 compile: 'm42 ^42' classified: #cat2. self t5: (self createTraitNamed: #T5 uses: self t1 + self t2). self t5 compile: 'm51 ^super foo' classified: #cat1. self t5 compile: 'm52 ^ self class bar' classified: #cat1. self t5 compile: 'm53 ^ self class bar' classified: #cat1. self t6: (self createTraitNamed: #T6 uses: (self t1 + self t2) @ { (#m22Alias -> #m22) }). self c1: (self createClassNamed: #C1 superclass: Object uses: { }). self c1 compile: 'foo ^true' classified: #accessing. self t1 compile: 'm11 ^11' classified: #cat1. self t1 compile: 'm12 ^12' classified: #cat2. self t1 compile: 'm13 ^self m12' classified: #cat3. self c2: (self createClassNamed: #C2 superclass: self c1 uses: self t5 - { #m11 }). self c2 compile: 'foo ^false' classified: #private. self c2 compile: 'bar ^self foo' classified: #private. self setUpTrivialRequiresFixture. self setUpTwoLevelRequiresFixture. self setUpTranslatingRequiresFixture]. SystemChangeNotifier uniqueInstance notify: self ofAllSystemChangesUsing: #codeChangedEvent:! ----- Method: TraitsResource>>setUpTranslatingRequiresFixture (in category 'as yet unclassified') ----- setUpTranslatingRequiresFixture self c6: (self createClassNamed: #C6 superclass: ProtoObject uses: { }). ProtoObject removeSubclass: self c6. self c6 superclass: nil. self c7: (self createClassNamed: #C7 superclass: self c6 uses: { }). self c8: (self createClassNamed: #C8 superclass: self c7 uses: { }). self c6 compile: 'foo ^self x' classified: #accessing. self c7 compile: 'foo ^3' classified: #accessing. self c7 compile: 'bar ^super foo' classified: #accessing. self c8 compile: 'bar ^self blah' classified: #accessing! ----- Method: TraitsResource>>setUpTrivialRequiresFixture (in category 'as yet unclassified') ----- setUpTrivialRequiresFixture self c3: (self createClassNamed: #C3 superclass: ProtoObject uses: { }). ProtoObject removeSubclass: self c3. self c3 superclass: nil. self c3 compile: 'foo ^self bla' classified: #accessing! ----- Method: TraitsResource>>setUpTwoLevelRequiresFixture (in category 'as yet unclassified') ----- setUpTwoLevelRequiresFixture self c4: (self createClassNamed: #C4 superclass: ProtoObject uses: { }). ProtoObject removeSubclass: self c4. self c4 superclass: nil. self c5: (self createClassNamed: #C5 superclass: self c4 uses: { }). self c4 compile: 'foo ^self blew' classified: #accessing. self c5 compile: 'foo ^self blah' classified: #accessing! ----- Method: TraitsResource>>t1 (in category 'accessing') ----- t1 ^t1! ----- Method: TraitsResource>>t1: (in category 'accessing') ----- t1: anObject ^t1 := anObject! ----- Method: TraitsResource>>t2 (in category 'accessing') ----- t2 ^t2! ----- Method: TraitsResource>>t2: (in category 'accessing') ----- t2: anObject ^t2 := anObject! ----- Method: TraitsResource>>t3 (in category 'accessing') ----- t3 ^t3! ----- Method: TraitsResource>>t3: (in category 'accessing') ----- t3: anObject ^t3 := anObject! ----- Method: TraitsResource>>t4 (in category 'accessing') ----- t4 ^t4! ----- Method: TraitsResource>>t4: (in category 'accessing') ----- t4: anObject ^t4 := anObject! ----- Method: TraitsResource>>t5 (in category 'accessing') ----- t5 ^t5! ----- Method: TraitsResource>>t5: (in category 'accessing') ----- t5: anObject ^t5 := anObject! ----- Method: TraitsResource>>t6 (in category 'accessing') ----- t6 ^t6! ----- Method: TraitsResource>>t6: (in category 'accessing') ----- t6: anObject ^t6 := anObject! ----- Method: TraitsResource>>tearDown (in category 'as yet unclassified') ----- tearDown | behaviorName | SystemChangeNotifier uniqueInstance noMoreNotificationsFor: self. self createdClassesAndTraits do: [:aClassOrTrait | behaviorName := aClassOrTrait name. Smalltalk at: behaviorName ifPresent: [:classOrTrait | classOrTrait removeFromSystem]. ChangeSet current removeClassChanges: behaviorName]. createdClassesAndTraits := self t1: (self t2: (self t3: (self t4: (self t5: (self t6: (self c1: (self c2: (self c3: (self c4: (self c5: (self c6: (self c7: (self c8: nil)))))))))))))! TestCase subclass: #TraitsTestCase instanceVariableNames: 'createdClassesAndTraits' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! TraitsTestCase subclass: #ClassTraitTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: ClassTraitTest>>testChanges (in category 'testing') ----- testChanges "Test the most important features to ensure that general functionality of class traits are working." "self run: #testChanges" | classTrait | classTrait := self t1 classTrait. classTrait compile: 'm1ClassSide ^17' classified: 'mycategory'. "local selectors" self assert: (classTrait includesLocalSelector: #m1ClassSide). self deny: (classTrait includesLocalSelector: #otherSelector). "propagation" self assert: (self t5 classSide methodDict includesKey: #m1ClassSide). self assert: (self c2 class methodDict includesKey: #m1ClassSide). self shouldnt: [self c2 m1ClassSide] raise: Error. self assert: self c2 m1ClassSide = 17. "category" self assert: (self c2 class organization categoryOfElement: #m1ClassSide) = 'mycategory'. "conflicts" self t2 classSide compile: 'm1ClassSide' classified: 'mycategory'. self assert: (self c2 class methodDict includesKey: #m1ClassSide). self deny: (self c2 class includesLocalSelector: #m1ClassSide). self should: [self c2 m1ClassSide] raise: Error. "conflict category" self assert: (self c2 class organization categoryOfElement: #m1ClassSide) = #mycategory! ----- Method: ClassTraitTest>>testConflictsAliasesAndExclusions (in category 'testing') ----- testConflictsAliasesAndExclusions "conflict" self t1 classTrait compile: 'm2ClassSide: x ^99' classified: 'mycategory'. self assert: (self t1 classTrait includesLocalSelector: #m2ClassSide:). self assert: (self t5 classTrait >> #m2ClassSide:) isConflict. self assert: (self c2 class >> #m2ClassSide:) isConflict. "exclusion and alias" self assert: self t5 classSide traitComposition asString = 'T1 classTrait + T2 classTrait'. self t5 classSide uses: (self t1 classTrait @ { (#m2ClassSideAlias1: -> #m2ClassSide:) } + self t2 classTrait) @ { (#m2ClassSideAlias2: -> #m2ClassSide:) } - { #m2ClassSide: }. self deny: (self t5 classTrait >> #m2ClassSide:) isConflict. self deny: (self c2 class >> #m2ClassSide:) isConflict. self assert: (self c2 m2ClassSideAlias1: 13) = 99. self assert: (self c2 m2ClassSideAlias2: 13) = 13! ----- Method: ClassTraitTest>>testInitialization (in category 'testing') ----- testInitialization "self run: #testInitialization" | classTrait | classTrait := self t1 classTrait. self assert: self t1 hasClassTrait. self assert: self t1 classTrait == classTrait. self assert: classTrait isClassTrait. self assert: classTrait classSide == classTrait. self deny: classTrait isBaseTrait. self assert: classTrait baseTrait == self t1. "assert classtrait methods are propagated to users when setting traitComposition" self assert: self t4 hasClassTrait. self assert: self t5 hasClassTrait. self assert: (self t2 classSide includesLocalSelector: #m2ClassSide:). self assert: (self t4 classSide methodDict includesKey: #m2ClassSide:). self assert: (self t5 classSide methodDict includesKey: #m2ClassSide:). self assert: (self c2 m2ClassSide: 17) = 17! ----- Method: ClassTraitTest>>testUsers (in category 'testing') ----- testUsers self assert: self t2 classSide users size = 3. self assert: (self t2 classSide users includesAllOf: { (self t4 classTrait). (self t5 classTrait). (self t6 classTrait) }). self assert: self t5 classSide users size = 1. self assert: self t5 classSide users anyOne = self c2 class. self c2 uses: self t1 + self t5. self assert: self t5 classSide users size = 1. self assert: self t5 classSide users anyOne = self c2 class. self c2 uses: self t2 asTraitComposition. self assert: self t5 classSide users isEmpty! TraitsTestCase subclass: #PureBehaviorTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: PureBehaviorTest>>testChangeSuperclass (in category 'testing-applying trait composition') ----- testChangeSuperclass "self run: #testChangeSuperclass" "Test that when the superclass of a class is changed the non-local methods of the class sending super are recompiled to correctly store the new superclass." | aC2 newSuperclass | aC2 := self c2 new. "C1 is current superclass of C2" self assert: aC2 m51. self assert: self c2 superclass == self c1. self deny: (self c2 localSelectors includes: #m51). "change superclass of C2 from C1 to X" newSuperclass := self createClassNamed: #X superclass: Object uses: {}. newSuperclass subclass: self c2 name uses: self c2 traitComposition instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: self c2 category. self assert: self c2 superclass == newSuperclass. newSuperclass compile: 'foo ^17'. self assert: aC2 m51 = 17. self deny: (self c2 localSelectors includes: #m51). self c2 compile: 'm51 ^19'. self assert: aC2 m51 = 19. self deny: (self c2 >> #m52) == (self t5 >> #m52). "no sharing!!" ! ----- Method: PureBehaviorTest>>testClassesWithTraits (in category 'testing-applying trait composition') ----- testClassesWithTraits "self debug: #testClassesWithTraits" self assert: (self c1 methodDict includesKey: #foo). self assert: (self c2 methodDict includesKey: #bar). self assert: (self c2 methodDict includesKey: #m51). self assert: (self c2 methodDict includesKey: #m12). self assert: (self c2 methodDict includesKey: #m13). self assert: (self c2 methodDict includesKey: #m21). self assert: (self c2 methodDict includesKey: #m22). self deny: self c1 class hasTraitComposition. self assert: self c2 class hasTraitComposition. self assert: (self c2 class traitComposition size = 1). self assert: (self c2 class includesTrait: self t5 classTrait)! ----- Method: PureBehaviorTest>>testIsAliasSelector (in category 'testing') ----- testIsAliasSelector self deny: (self t1 isAliasSelector: #m11). self deny: (self t1 isAliasSelector: #foo). "directly" self assert: (self t6 isAliasSelector: #m22Alias). self deny: (self t6 isAliasSelector: #m22). "indirectly" self c1 uses: self t6. self assert: (self c1 isAliasSelector: #m22Alias). self deny: (self c1 isAliasSelector: #m22)! ----- Method: PureBehaviorTest>>testIsLocalAliasSelector (in category 'testing') ----- testIsLocalAliasSelector self deny: (self t1 isLocalAliasSelector: #m11). self deny: (self t1 isLocalAliasSelector: #foo). "directly" self assert: (self t6 isLocalAliasSelector: #m22Alias). self deny: (self t6 isLocalAliasSelector: #m22). "indirectly" self c1 uses: self t6 asTraitComposition. self deny: (self c1 isLocalAliasSelector: #m22Alias). self deny: (self c1 isLocalAliasSelector: #m22)! ----- Method: PureBehaviorTest>>testLocalSelectors (in category 'testing') ----- testLocalSelectors "self run: #testLocalSelectors" self assert: self t3 localSelectors size = 3. self assert: (self t3 localSelectors includesAllOf: #(#m31 #m32 #m33 )). self assert: (self t3 includesLocalSelector: #m32). self deny: (self t3 includesLocalSelector: #inexistantSelector). self assert: self t5 localSelectors size = 3. self assert: (self t5 localSelectors includes: #m51). self assert: (self t5 includesLocalSelector: #m51). self deny: (self t5 includesLocalSelector: #m11). self t5 removeSelector: #m51. self deny: (self t3 includesLocalSelector: #m51). self deny: (self t5 includesLocalSelector: #m11). self assert: self t5 localSelectors size = 2. self t5 compile: 'm52 ^self'. self assert: self t5 localSelectors size = 2. self assert: (self t5 localSelectors includes: #m52). "test that propagated methods do not get in as local methods" self t2 compile: 'local2 ^self'. self deny: (self t5 includesLocalSelector: #local2). self assert: self t5 localSelectors size = 2. self assert: (self t5 localSelectors includes: #m52). self assert: self c2 localSelectors size = 2. self assert: (self c2 localSelectors includesAllOf: #(#foo #bar ))! ----- Method: PureBehaviorTest>>testMethodCategoryReorganization (in category 'testing') ----- testMethodCategoryReorganization "self run: #testMethodCategory" self t1 compile: 'm1' classified: 'category1'. self assert: (self t5 organization categoryOfElement: #m1) = #category1. self assert: (self c2 organization categoryOfElement: #m1) = #category1. self t1 organization classify: #m1 under: #category2 suppressIfDefault: true. self assert: (self t5 organization categoryOfElement: #m1) = #category2. self assert: (self c2 organization categoryOfElement: #m1) = #category2! ----- Method: PureBehaviorTest>>testOwnMethodsTakePrecedenceOverTraitsMethods (in category 'testing-applying trait composition') ----- testOwnMethodsTakePrecedenceOverTraitsMethods "First create a trait with no subtraits and then add subtrait t1 which implements m11 as well." | trait | trait := self createTraitNamed: #TraitsTestTrait uses: { }. trait compile: 'm11 ^999'. self assert: trait methodDict size = 1. self assert: (trait methodDict at: #m11) decompileString = 'm11 ^ 999'. self createTraitNamed: #TraitsTestTrait uses: self t1. self assert: trait methodDict size = 3. self assert: (trait methodDict keys includesAllOf: #(#m11 #m12 #m13 )). self assert: (trait methodDict at: #m11) decompileString = 'm11 ^ 999'. self assert: (trait methodDict at: #m12) decompileString = 'm12 ^ 12'! ----- Method: PureBehaviorTest>>testPropagationOfChangesInTraits (in category 'testing-applying trait composition') ----- testPropagationOfChangesInTraits | aC2 | aC2 := self c2 new. self assert: self c2 methodDict size = 9. self t1 compile: 'zork ^false'. self assert: self c2 methodDict size = 10. self deny: aC2 zork. self t1 removeSelector: #m12. self assert: self c2 methodDict size = 9. self should: [aC2 m12] raise: MessageNotUnderstood. self assert: aC2 m21 = 21. self t2 compile: 'm21 ^99'. self assert: aC2 m21 = 99! ----- Method: PureBehaviorTest>>testPropagationOfChangesInTraitsToAliasMethods (in category 'testing-applying trait composition') ----- testPropagationOfChangesInTraitsToAliasMethods | anObject | anObject := (self createClassNamed: #TraitsTestAliasTestClass superclass: Object uses: self t6) new. self assert: anObject m22Alias = 22. "test update alias method" self t2 compile: 'm22 ^17'. self assert: anObject m22Alias = 17. "removing original method should also remove alias method" self t2 removeSelector: #m22. self should: [anObject m22Alias] raise: MessageNotUnderstood! ----- Method: PureBehaviorTest>>testPropagationOfChangesInTraitsToAliasMethodsWhenOriginalMethodIsExcluded (in category 'testing-applying trait composition') ----- testPropagationOfChangesInTraitsToAliasMethodsWhenOriginalMethodIsExcluded "Assert that alias method is updated although the original method is excluded from this user." | anObject | anObject := (self createClassNamed: #TraitsTestAliasTestClass superclass: Object uses: self t1 @ { (#aliasM11 -> #m11) } - { #m11 }) new. self assert: anObject aliasM11 = 11. self deny: (anObject class methodDict includesKey: #m11). self t1 compile: 'm11 ^17'. self assert: anObject aliasM11 = 17! ----- Method: PureBehaviorTest>>testPropagationWhenTraitCompositionModifications (in category 'testing-applying trait composition') ----- testPropagationWhenTraitCompositionModifications "Test that the propagation mechanism works when setting new traitCompositions." self assert: self c2 methodDict size = 9. "2 + (3+(3+2))-1" "removing methods" self createTraitNamed: #T5 uses: self t1 + self t2 - { #m21. #m22 }. self assert: self c2 methodDict size = 7. "adding methods" self createTraitNamed: #T2 uses: self t3. self assert: self c2 methodDict size = 10. self assert: (self c2 methodDict keys includesAllOf: #(#m31 #m32 #m33 ))! ----- Method: PureBehaviorTest>>testRemovingMethods (in category 'testing') ----- testRemovingMethods "When removing a local method, assure that the method from the trait is installed instead and that the users are updated." "self run: #testRemovingMethods" "Classes" self c2 compile: 'm12 ^0' classified: #xxx. self assert: (self c2 includesLocalSelector: #m12). self c2 removeSelector: #m12. self deny: (self c2 includesLocalSelector: #m12). self assert: (self c2 selectors includes: #m12). "Traits" self t5 compile: 'm12 ^0' classified: #xxx. self assert: self c2 new m12 = 0. self t5 removeSelector: #m12. self deny: (self t5 includesLocalSelector: #m12). self assert: (self t5 selectors includes: #m12). self assert: self c2 new m12 = 12! ----- Method: PureBehaviorTest>>testSuperSends (in category 'testing-applying trait composition') ----- testSuperSends | aC2 | aC2 := self c2 new. self assert: aC2 m51. self deny: aC2 foo. self deny: aC2 bar! ----- Method: PureBehaviorTest>>testTraitCompositionModifications (in category 'testing-applying trait composition') ----- testTraitCompositionModifications self assert: self t6 methodDict size = 6. self assert: (self t6 sourceCodeAt: #m22Alias) asString = 'm22Alias ^22'. self t6 uses: self t2 asTraitComposition. self assert: self t6 methodDict size = 2. self deny: (self t6 methodDict includesKey: #m22Alias). self t6 uses: self t1 @ { (#m13Alias -> #m13) } - { #m11. #m12 } + self t2. self assert: self t6 methodDict size = 4. self assert: (self t6 methodDict keys includesAllOf: #(#m13 #m13Alias #m21 #m22 )). self assert: (self t6 sourceCodeAt: #m13Alias) asString = 'm13Alias ^self m12'! ----- Method: PureBehaviorTest>>testTraitCompositionWithCycles (in category 'testing-applying trait composition') ----- testTraitCompositionWithCycles self should: [self t1 uses: self t1 asTraitComposition] raise: Error. self t2 uses: self t3 asTraitComposition. self should: [self t3 uses: self t5 asTraitComposition] raise: Error! ----- Method: PureBehaviorTest>>testUpdateWhenLocalMethodRemoved (in category 'testing-applying trait composition') ----- testUpdateWhenLocalMethodRemoved | aC2 | aC2 := self c2 new. self t5 compile: 'foo ^123'. self deny: aC2 foo. self c2 removeSelector: #foo. self assert: aC2 foo = 123! ----- Method: PureBehaviorTest>>traitOrClassOfSelector (in category 'testing') ----- traitOrClassOfSelector "self run: #traitOrClassOfSelector" "locally defined in trait or class" self assert: (self t1 >> #m12) originalTraitOrClass = self t1. self assert: (self c1 >> #foo) originalTraitOrClass = self c1. "not locally defined - simple" self assert: (self t4 >> #m21) originalTraitOrClass = self t2. self assert: (self c2 >> #m51) originalTraitOrClass = self t5. "not locally defined - into nested traits" self assert: (self c2 >> #m22) originalTraitOrClass = self t2. "not locally defined - aliases" self assert: (self t6 >> #m22Alias) originalTraitOrClass = self t2. "class side" self assert: (self t2 classSide >> #m2ClassSide:) originalTraitOrClass = self t2 classSide. self assert: (self t6 classSide >> #m2ClassSide:) originalTraitOrClass = self t2 classSide! TraitsTestCase subclass: #TraitCompositionTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: TraitCompositionTest>>testAliasCompositions (in category 'testing-basic') ----- testAliasCompositions "unary" self shouldnt: [self t2 uses: self t1 @ { (#aliasM11 -> #m11) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#alias: -> #m11) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#alias:x:y: -> #m11) }] raise: TraitCompositionException. "binary" self t1 compile: '= anObject'. self shouldnt: [self t2 uses: self t1 @ { (#equals: -> #=) }] raise: TraitCompositionException. self shouldnt: [self t2 uses: self t1 @ { (#% -> #=) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#equals -> #=) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#equals:x: -> #=) }] raise: TraitCompositionException. "keyword" self t1 compile: 'x: a y: b z: c'. self should: [self t2 uses: self t1 @ { (#'==' -> #x:y:z:) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#x -> #x:y:z:) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#x: -> #x:y:z:) }] raise: TraitCompositionException. self should: [self t2 uses: self t1 @ { (#x:y: -> #x:y:z:) }] raise: TraitCompositionException. self shouldnt: [self t2 uses: self t1 @ { (#myX:y:z: -> #x:y:z:) }] raise: TraitCompositionException. "alias same as selector" self should: [self t2 uses: self t1 @ { (#m11 -> #m11) }] raise: TraitCompositionException. "same alias name used twice" self should: [self t2 uses: self t1 @ { (#alias -> #m11). (#alias -> #m12) }] raise: TraitCompositionException. "aliasing an alias" self should: [self t2 uses: self t1 @ { (#alias -> #m11). (#alias2 -> #alias) }] raise: TraitCompositionException! ----- Method: TraitCompositionTest>>testClassMethodsTakePrecedenceOverTraitsMethods (in category 'testing-enquiries') ----- testClassMethodsTakePrecedenceOverTraitsMethods | keys | keys := Set new. self t4 methodDict bindingsDo: [:each | keys add: each key]. self assert: keys size = 6. self assert: (keys includesAllOf: #( #m12 #m13 #m13 #m21 #m22 #m11 #m42 )). self assert: (self t4 methodDict at: #m11) decompileString = 'm11 ^ 41'! ----- Method: TraitCompositionTest>>testCompositionFromArray (in category 'testing-basic') ----- testCompositionFromArray | composition | composition := TraitComposition withAll: { (self t1) }. self assert: (composition isKindOf: TraitComposition). self assert: (composition traits includes: self t1). self assert: composition traits size = 1. composition := TraitComposition withAll: { (self t1). self t2 }. self assert: (composition isKindOf: TraitComposition). self assert: (composition traits includes: self t1). self assert: (composition traits includes: self t2). self assert: composition traits size = 2! ----- Method: TraitCompositionTest>>testEmptyTrait (in category 'testing-basic') ----- testEmptyTrait | composition | composition := TraitComposition withAll: {}. self assert: (composition isKindOf: TraitComposition). " self assert: composition transformations isEmpty. " self assert: composition traits isEmpty! ----- Method: TraitCompositionTest>>testInvalidComposition (in category 'testing-basic') ----- testInvalidComposition self shouldnt: [self t1 @ { (#a -> #b) } @ { (#x -> #y) }] raise: TraitCompositionException. self shouldnt: [(self t1 + self t2) @ { (#a -> #b) } @ { (#x -> #y) }] raise: TraitCompositionException. self shouldnt: [self t1 - { #a } - { #b }] raise: TraitCompositionException. self shouldnt: [self t1 + self t2 - { #a } - { #b }] raise: TraitCompositionException. self should: [(self t1 - { #x }) @ { (#a -> #b) }] raise: TraitCompositionException. self should: [(self t1 + self t2 - { #x }) @ { (#a -> #b) }] raise: TraitCompositionException. self should: [self t1 + self t1] raise: TraitCompositionException. self should: [(self t1 + self t2) @ { (#a -> #b) } + self t1] raise: TraitCompositionException. self should: [self t1 @ { (#a -> #m11). (#a -> #m12) }] raise: TraitCompositionException. self should: [self t1 @ { (#a -> #m11). (#b -> #a) }] raise: TraitCompositionException! ----- Method: TraitCompositionTest>>testPrinting (in category 'testing-basic') ----- testPrinting | composition1 composition2 | composition1 := ((self t1 - { #a } + self t2) @ { (#z -> #c) } - { #b. #c } + self t3 - { #d. #e } + self t4) @ { (#x -> #a). (#y -> #b) }. composition2 := self t4 @ { (#x -> #a). (#y -> #b) } + self t1 - { #a } + self t3 - { #d. #e } + self t2 - { #b. #c }. self assertPrints: composition1 printString like: 'T1 - {#a} + T2 @ {#z->#c} - {#b. #c} + T3 - {#d. #e} + T4 @ {#x->#a. #y->#b}'. self assertPrints: composition2 printString like: 'T4 @ {#x->#a. #y->#b} + T1 - {#a} + T3 - {#d. #e} + T2 - {#b. #c}'! ----- Method: TraitCompositionTest>>testProvidedMethodBindingsWithConflicts (in category 'testing-enquiries') ----- testProvidedMethodBindingsWithConflicts | traitWithConflict methodDict | traitWithConflict := self createTraitNamed: #TraitsTestTraitWithConflict uses: self t1 + self t4. methodDict := traitWithConflict methodDict. self assert: methodDict size = 6. self assert: (methodDict keys includesAllOf: #( #m11 #m12 #m13 #m21 #m22 #m42 )). self assert: (methodDict at: #m11) decompileString = 'm11 ^ self traitConflict'! ----- Method: TraitCompositionTest>>testSum (in category 'testing-basic') ----- testSum | composition | composition := self t1 + self t2 + self t3. self assert: (composition isKindOf: TraitComposition). self assert: (composition traits includes: self t1). self assert: (composition traits includes: self t2). self assert: (composition traits includes: self t3). self assert: composition traits size = 3! ----- Method: TraitCompositionTest>>testSumWithParenthesis (in category 'testing-basic') ----- testSumWithParenthesis | composition | composition := self t1 + (self t2 + self t3). self assert: (composition isKindOf: TraitComposition). self assert: (composition traits includes: self t1). self assert: (composition traits includes: self t2). self assert: (composition traits includes: self t3). self assert: composition traits size = 3. self assert: composition size = 3! TraitsTestCase subclass: #TraitFileOutTest instanceVariableNames: 'ca cb ta tb tc td' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: TraitFileOutTest>>categoryName (in category 'running') ----- categoryName ^'TraitsTests-FileOut'! ----- Method: TraitFileOutTest>>fileIn: (in category 'testing') ----- fileIn: fileName | prior file result | prior := ClassDescription traitImpl. [ ClassDescription traitImpl: Trait. file := FileStream readOnlyFileNamed: fileName. result := file fileIn ] ensure: [ file ifNotNil:[file close]. ClassDescription traitImpl: prior. ]. ^result! ----- Method: TraitFileOutTest>>setUp (in category 'running') ----- setUp super setUp. SystemOrganization addCategory: self categoryName. td := self createTraitNamed: #TD uses: {}. td compile: 'd' classified: #cat1. tc := self createTraitNamed: #TC uses: td. tc compile: 'c' classified: #cat1. tb := self createTraitNamed: #TB uses: td. tb compile: 'b' classified: #cat1. ta := self createTraitNamed: #TA uses: tb + tc @ {#cc->#c} - {#c}. ta compile: 'a' classified: #cat1. ca := self createClassNamed: #CA superclass: Object uses: {}. ca compile: 'ca' classified: #cat1. cb := self createClassNamed: #CB superclass: ca uses: ta. cb compile: 'cb' classified: #cat1. "make the class of cb also use tc:" cb class uses: ta classTrait + tc instanceVariableNames: ''.! ----- Method: TraitFileOutTest>>tearDown (in category 'running') ----- tearDown | dir | dir := FileDirectory default. self createdClassesAndTraits, self resourceClassesAndTraits do: [:each | dir deleteFileNamed: each asString , '.st' ifAbsent: []]. dir deleteFileNamed: self categoryName , '.st' ifAbsent: []. SystemOrganization removeSystemCategory: self categoryName. super tearDown! ----- Method: TraitFileOutTest>>testFileOutCategory (in category 'testing') ----- testFileOutCategory "File out whole system category, delete all classes and traits and then file them in again." "self run: #testFileOutCategory" | | SystemOrganization fileOutCategory: self categoryName. SystemOrganization removeSystemCategory: self categoryName. self deny: (Smalltalk keys includesAnyOf: #(CA CB TA TB TC TD)). self fileIn: self categoryName , '.st'.. self assert: (Smalltalk keys includesAllOf: #(CA CB TA TB TC TD)). ta := Smalltalk at: #TA. self assert: (ta isKindOf: Trait). self assert: ta traitComposition asString = 'TB + TC @ {#cc->#c} - {#c}'. self assert: (ta methodDict keys includesAllOf: #(a b cc)). cb := Smalltalk at: #CB. self assert: (cb isKindOf: Class). self assert: cb traitComposition asString = 'TA'. self assert: (cb methodDict keys includesAllOf: #(cb a b cc)). "test classSide traitComposition of CB" self assert: cb classSide traitComposition asString = 'TA classTrait + TC'. self assert: (cb classSide methodDict keys includesAllOf: #(d c)) ! ----- Method: TraitFileOutTest>>testFileOutTrait (in category 'testing') ----- testFileOutTrait "fileOut trait T6, remove it from system and then file it in again" "self run: #testFileOutTrait" | fileName | self t6 compile: 'localMethod: argument ^argument'. self t6 classSide compile: 'localClassSideMethod: argument ^argument'. self t6 fileOut. fileName := self t6 asString , '.st'. self resourceClassesAndTraits remove: self t6. self t6 removeFromSystem. self fileIn: fileName. self assert: (Smalltalk includesKey: #T6). TraitsResource current t6: (Smalltalk at: #T6). self resourceClassesAndTraits add: self t6. self assert: (self t6 isKindOf: Trait). self assert: self t6 traitComposition asString = 'T1 + T2 @ {#m22Alias->#m22}'. self assert: (self t6 methodDict keys includesAllOf: #( #localMethod: #m11 #m12 #m13 #m21 #m22 #m22Alias )). self assert: self t6 classSide methodDict size = 2. self assert: (self t6 classSide methodDict keys includesAllOf: #(#localClassSideMethod: #m2ClassSide: ))! ----- Method: TraitFileOutTest>>testRemovingMethods (in category 'testing') ----- testRemovingMethods "When removing a local method, assure that the method from the trait is installed instead and that the users are updated." "self run: #testRemovingMethods" "Classes" self c2 compile: 'm12 ^0' classified: #xxx. self assert: (self c2 includesLocalSelector: #m12). self c2 removeSelector: #m12. self deny: (self c2 includesLocalSelector: #m12). self assert: (self c2 selectors includes: #m12). "Traits" self t5 compile: 'm12 ^0' classified: #xxx. self assert: self c2 new m12 = 0. self t5 removeSelector: #m12. self deny: (self t5 includesLocalSelector: #m12). self assert: (self t5 selectors includes: #m12). self assert: self c2 new m12 = 12! TraitsTestCase subclass: #TraitMethodDescriptionTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: TraitMethodDescriptionTest>>testArgumentNames (in category 'running') ----- testArgumentNames self t1 compile: 'zork1: myArgument zork2: mySecondArgument ^true'. self t2 compile: 'zork1: myArgument zork2: somethingElse ^false'. self assert: ((self t5 sourceCodeAt: #zork1:zork2:) asString beginsWith: 'zork1: arg1 zork2: arg2'). self t1 compile: 'zork1: myArgument zork2: mySecondArgument ^true'. self t2 compile: 'zork1: somethingElse zork2: myArgument ^false'. self assert: ((self t5 sourceCodeAt: #zork1:zork2:) asString beginsWith: 'zork1: arg1 zork2: arg2')! ----- Method: TraitMethodDescriptionTest>>testCategories (in category 'running') ----- testCategories self assert: (self t4 organization categoryOfElement: #m21) = #cat1. self assert: (self t4 organization categoryOfElement: #m22) = #cat2. self assert: (self t4 organization categoryOfElement: #m11) = #catX. self assert: (self t4 organization categoryOfElement: #m12) = #cat2. self assert: (self t4 organization categoryOfElement: #m13) = #cat3. self assert: (self t6 organization categoryOfElement: #m22Alias) = #cat2. self t2 organization classify: #m22 under: #catX. self assert: (self t4 organization categoryOfElement: #m22) = #catX. self assert: (self t6 organization categoryOfElement: #m22Alias) = #catX. self t6 organization classify: #m22 under: #catY. self t6 organization classify: #m22Alias under: #catY. self t2 organization classify: #m22 under: #catZ. "XXX: The following test is commented out for now. The policy is to *always* reclassify the method if the base method is reclassified. That results from the requirement that the base construction should always be repeatable (in fact, one could argue that reclassification of methods from traits is invalid without some explicit transformation)." false ifTrue:[ self assert: (self t6 organization categoryOfElement: #m22) = #catY. self assert: (self t6 organization categoryOfElement: #m22Alias) = #catY. ]. self t1 compile: 'mA' classified: #catA. self assert: (self t4 organization categoryOfElement: #mA) = #catA. self t1 organization classify: #mA under: #cat1. self assert: (self t4 organization categories includes: #catA) not! ----- Method: TraitMethodDescriptionTest>>testConflictMethodCreation (in category 'running') ----- testConflictMethodCreation "Generate conflicting methods between t1 and t2 and check the resulting method in Trait t5 (or c2). Also test selectors like foo:x (without space) or selectors with CRs." "unary" self t2 compile: 'm12 ^false'. self assert: ((self t5 sourceCodeAt: #m12) asString beginsWith: 'm12'). self should: [self c2 new m12] raise: Error. "binary" self t1 compile: '@ myArgument ^true'. self t2 compile: '@myArgument ^false'. self assert: ((self t5 sourceCodeAt: #@) asString beginsWith: '@ arg1'). self should: [self c2 new @ 17] raise: Error. "keyword" self t1 compile: 'zork: myArgument ^true'. self t2 compile: 'zork: myArgument ^false'. self assert: ((self t5 sourceCodeAt: #zork:) asString beginsWith: 'zork: arg1'). self should: [self c2 new zork: 17] raise: Error. self t1 compile: 'zork:myArgument ^true'. self t2 compile: 'zork:myArgument ^false'. self assert: ((self t5 sourceCodeAt: #zork:) asString beginsWith: 'zork: arg1'). self should: [self c2 new zork: 17] raise: Error. self t1 compile: 'zork1: myArgument zork2: mySecondArgument ^true'. self t2 compile: 'zork1: anObject zork2: anotherObject ^false'. self assert: ((self t5 sourceCodeAt: #zork1:zork2:) asString beginsWith: 'zork1: arg1 zork2: arg2'). self should: [self c2 new zork1: 1 zork2: 2] raise: Error! ----- Method: TraitMethodDescriptionTest>>testConflictingCategories (in category 'running') ----- testConflictingCategories | t7 t8 | self t2 compile: 'm11' classified: #catY. self assert: (self t4 organization categoryOfElement: #m11) = #catX. self assert: (self t5 organization categoryOfElement: #m11) = #'conflict methods'. "was: #cat1" t7 := self createTraitNamed: #T7 uses: self t1 + self t2. self assert: (t7 organization categoryOfElement: #m11) = #'conflict methods'. "was: ClassOrganizer ambiguous" self t1 removeSelector: #m11. self assert: (self t4 organization categoryOfElement: #m11) = #catX. self assert: (self t5 organization categoryOfElement: #m11) = #catY. self assert: (t7 organization categoryOfElement: #m11) = #catY. self deny: (t7 organization categories includes: #'conflict methods' "was: ClassOrganizer ambiguous"). self t1 compile: 'm11' classified: #cat1. t8 := self createTraitNamed: #T8 uses: self t1 + self t2. t8 organization classify: #m11 under: #cat1. self t1 organization classify: #m11 under: #catZ. self assert: (self t4 organization categoryOfElement: #m11) = #catX. self assert: (self t5 organization categoryOfElement: #m11) = #'conflict methods'. "was: #catY" self assert: (t8 organization categoryOfElement: #m11) = #'conflict methods'. "was: #catZ"! TraitsTestCase subclass: #TraitSystemTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: TraitSystemTest>>testAllClassesAndTraits (in category 'testing') ----- testAllClassesAndTraits "self debug: #testAllClassesAndTraits" | trait | trait := self t1. self assert: (Smalltalk allClassesAndTraits includes: trait). self deny: (Smalltalk allClasses includes: trait). ! ----- Method: TraitSystemTest>>testAllImplementedMessagesWithout (in category 'testing') ----- testAllImplementedMessagesWithout "self debug: #testAllImplementedMessagesWithout" self t6 compile: 'das2qwdqwd'. self assert: (SystemNavigation default allImplementedMessages includes: #das2qwdqwd). self deny: (SystemNavigation default allImplementedMessages includes: #qwdqwdqwdc).! ----- Method: TraitSystemTest>>testAllSentMessages (in category 'testing') ----- testAllSentMessages "self debug: #testAllSentMessages" self t1 compile: 'foo 1 dasoia'. self assert: (SystemNavigation default allSentMessages includes: 'dasoia' asSymbol). self deny: (SystemNavigation default allSentMessages includes: 'nioaosi' asSymbol).! TraitsTestCase subclass: #TraitTest instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'TraitsTests-Kernel'! ----- Method: TraitTest>>testAddAndRemoveMethodsFromSubtraits (in category 'testing') ----- testAddAndRemoveMethodsFromSubtraits | aC2 | aC2 := self c2 new. self assert: aC2 m51. self t5 removeSelector: #m51. self should: [aC2 m51] raise: MessageNotUnderstood. self t1 compile: 'foo ^true'. self deny: aC2 foo. self t1 compile: 'm51 ^self'. self shouldnt: [aC2 m51] raise: MessageNotUnderstood. self assert: aC2 m51 == aC2! ----- Method: TraitTest>>testAddAndRemoveMethodsInClassOrTrait (in category 'testing') ----- testAddAndRemoveMethodsInClassOrTrait | aC2 | aC2 := self c2 new. self assert: aC2 m51. self c2 compile: 'm51 ^123'. self assert: aC2 m51 = 123. self c2 removeSelector: #m51. self shouldnt: [aC2 m51] raise: MessageNotUnderstood. self assert: aC2 m51. self t4 removeSelector: #m11. self assert: (self t4 methodDict includesKey: #m11)! ----- Method: TraitTest>>testAllClassVarNames (in category 'testing') ----- testAllClassVarNames self assert: self t1 allClassVarNames isEmpty! ----- Method: TraitTest>>testCompositionCopy (in category 'testing') ----- testCompositionCopy | t6compositionCopyFirst c2compositionCopy | self assert: (self t1 + self t2) allTraits = (self t1 + self t2) copyTraitExpression allTraits. self assert: (self t1 classTrait + self t2 classTrait) allTraits = (self t1 classTrait + self t2 classTrait) copyTraitExpression allTraits. self assert: self t6 traitComposition allTraits = self t6 traitComposition copyTraitExpression allTraits. self assert: self t6 asTraitComposition copyTraitExpression allTraits = { (self t1). (self t2). (self t6) }. false ifTrue:[ "make no undue sharing happens of exclusions and aliases after an expression copy" t6compositionCopyFirst := self t6 traitComposition copyTraitExpression. t6compositionCopyFirst transformations at: 1 put: #m22Alias -> #m33. self assert: self t6 traitComposition transformations second aliases first value = #m22. c2compositionCopy := self c2 traitComposition copyTraitExpression. c2compositionCopy transformations first exclusions at: 1 put: #m4. self c2 traitComposition transformations first exclusions = #(#m11 ) ].! ----- Method: TraitTest>>testExplicitRequirement (in category 'testing') ----- testExplicitRequirement "self run: #testExplicitRequirement" self t1 compile: 'm self explicitRequirement'. self t2 compile: 'm ^true'. self deny: (self t4 >> #m) == (self t2 >> #m). "no sharing!!" self assert: self c2 new m. self t2 removeSelector: #m. self deny: (self t5 >> #m) == (self t1 >> #m). "no sharing!!" self should: [self c2 new m] raise: Error! ----- Method: TraitTest>>testMarkerMethods (in category 'testing') ----- testMarkerMethods "self debug: #testMarkerMethods" self t1 compile: 'm1 self foo bar'. self assert: (self t1 >> #m1) markerOrNil isNil. self t1 compile: 'm2 self requirement'. self assert: (self t1 >> #m2) markerOrNil == #requirement. self t1 compile: 'm3 ^self requirement'. self assert: (self t1 >> #m3) markerOrNil == #requirement.! ----- Method: TraitTest>>testPrinting (in category 'testing') ----- testPrinting self assertPrints: self t6 definitionST80 like: 'Trait named: #T6 uses: T1 + T2 @ {#m22Alias->#m22} category: ''TraitsTests-Kernel'''! ----- Method: TraitTest>>testPrintingClassSide (in category 'testing') ----- testPrintingClassSide "self run: #testPrintingClassSide" self assertPrints: self t6 classSide definitionST80 like: 'T6 classTrait uses: T1 classTrait + T2 classTrait'! ----- Method: TraitTest>>testRemoveFromSystem (in category 'testing') ----- testRemoveFromSystem self t4 removeFromSystem. self deny: (Smalltalk includesKey: #T4). self assert: self t4 name = 'AnObsoleteT4'. self assert: self t4 methodDict isEmpty. self deny: (self t1 users includes: self t4)! ----- Method: TraitTest>>testRequirement (in category 'testing') ----- testRequirement "self run: #testRequirement" self t1 compile: 'm self requirement'. self t2 compile: 'm ^true'. self deny: (self t4 >> #m) == (self t2 >> #m). "no sharing!!" self assert: self c2 new m. self t2 removeSelector: #m. self deny: (self t5 >> #m) == (self t1 >> #m). "no sharing!!" self should: [self c2 new m] raise: Error! ----- Method: TraitTest>>testTraitFromPattern (in category 'testing') ----- testTraitFromPattern | newTrait | newTrait := self createTraitNamed: #TTraitTestBaseTrait uses: {}. self assert: (Utilities classFromPattern: 'TTraitTestBaseT' withCaption: '') = newTrait.! ----- Method: TraitTest>>testTraitMethodClass (in category 'testing') ----- testTraitMethodClass "Tests that the #methodClass of a trait method isn't screwed up" | baseTrait classA methodA classB methodB traitMethod | baseTrait := self createTraitNamed: #TraitTestBaseTrait uses:{}. baseTrait compileSilently: 'traitMethod' classified: 'tests'. traitMethod := baseTrait compiledMethodAt: #traitMethod. self assert: traitMethod methodClass == baseTrait. classA := self createClassNamed: #TraitTestMethodClassA superclass: Object uses: baseTrait. methodA := classA compiledMethodAt: #traitMethod. self assert: traitMethod methodClass == baseTrait. self assert: methodA methodClass == classA. classB := self createClassNamed: #TraitTestMethodClassB superclass: Object uses: baseTrait. methodB := classB compiledMethodAt: #traitMethod. self assert: traitMethod methodClass == baseTrait. self assert: methodA methodClass == classA. self assert: methodB methodClass == classB.! ----- Method: TraitTest>>testTraitMethodSelector (in category 'testing') ----- testTraitMethodSelector "Tests that the #selector of a trait method isn't screwed up when aliasing traits" | baseTrait classA methodA classB methodB traitMethod | baseTrait := self createTraitNamed: #TraitTestBaseTrait uses:{}. baseTrait compileSilently: 'traitMethod' classified: 'tests'. traitMethod := baseTrait compiledMethodAt: #traitMethod. self assert: traitMethod selector == #traitMethod. classA := self createClassNamed: #TraitTestMethodClassA superclass: Object uses: {baseTrait @ {#methodA -> #traitMethod}}. methodA := classA compiledMethodAt: #methodA. self assert: traitMethod selector == #traitMethod. self assert: methodA selector == #methodA. classB := self createClassNamed: #TraitTestMethodClassB superclass: Object uses: {baseTrait @ {#methodB -> #traitMethod}}. methodB := classB compiledMethodAt: #methodB. self assert: traitMethod selector == #traitMethod. self assert: methodA selector == #methodA. self assert: methodB selector == #methodB.! ----- Method: TraitTest>>testUsers (in category 'testing') ----- testUsers self assert: self t1 users size = 3. self assert: (self t1 users includesAllOf: {self t4. self t5. self t6 }). self assert: self t3 users isEmpty. self assert: self t5 users size = 1. self assert: self t5 users anyOne = self c2. self c2 uses: self t1 + self t5. self assert: self t5 users size = 1. self assert: self t5 users anyOne = self c2. self c2 uses: self t2 asTraitComposition. self assert: self t5 users isEmpty! ----- Method: TraitsTestCase class>>resources (in category 'as yet unclassified') ----- resources ^{TraitsResource}! ----- Method: TraitsTestCase>>assertPrints:like: (in category 'utility') ----- assertPrints: aString like: anotherString self assert: (aString copyWithout: $ ) = (anotherString copyWithout: $ )! ----- Method: TraitsTestCase>>c1 (in category 'accessing') ----- c1 ^TraitsResource current c1! ----- Method: TraitsTestCase>>c2 (in category 'accessing') ----- c2 ^TraitsResource current c2! ----- Method: TraitsTestCase>>c3 (in category 'accessing') ----- c3 ^TraitsResource current c3! ----- Method: TraitsTestCase>>c4 (in category 'accessing') ----- c4 ^TraitsResource current c4! ----- Method: TraitsTestCase>>c5 (in category 'accessing') ----- c5 ^TraitsResource current c5! ----- Method: TraitsTestCase>>c6 (in category 'accessing') ----- c6 ^TraitsResource current c6! ----- Method: TraitsTestCase>>c7 (in category 'accessing') ----- c7 ^TraitsResource current c7! ----- Method: TraitsTestCase>>c8 (in category 'accessing') ----- c8 ^TraitsResource current c8! ----- Method: TraitsTestCase>>categoryName (in category 'running') ----- categoryName ^self class category! ----- Method: TraitsTestCase>>createClassNamed:superclass:uses: (in category 'utility') ----- createClassNamed: aSymbol superclass: aClass uses: aTraitComposition | class | class := aClass subclass: aSymbol uses: aTraitComposition instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: self categoryName. self createdClassesAndTraits add: class. ^class! ----- Method: TraitsTestCase>>createTraitNamed:uses: (in category 'utility') ----- createTraitNamed: aSymbol uses: aTraitComposition | trait | trait := Trait named: aSymbol uses: aTraitComposition category: self categoryName env: Smalltalk. self createdClassesAndTraits add: trait. ^trait! ----- Method: TraitsTestCase>>createdClassesAndTraits (in category 'utility') ----- createdClassesAndTraits createdClassesAndTraits ifNil: [ createdClassesAndTraits := OrderedCollection new]. ^createdClassesAndTraits! ----- Method: TraitsTestCase>>resourceClassesAndTraits (in category 'utility') ----- resourceClassesAndTraits ^TraitsResource current createdClassesAndTraits! ----- Method: TraitsTestCase>>t1 (in category 'accessing') ----- t1 ^TraitsResource current t1! ----- Method: TraitsTestCase>>t2 (in category 'accessing') ----- t2 ^TraitsResource current t2! ----- Method: TraitsTestCase>>t3 (in category 'accessing') ----- t3 ^TraitsResource current t3! ----- Method: TraitsTestCase>>t4 (in category 'accessing') ----- t4 ^TraitsResource current t4! ----- Method: TraitsTestCase>>t5 (in category 'accessing') ----- t5 ^TraitsResource current t5! ----- Method: TraitsTestCase>>t6 (in category 'accessing') ----- t6 ^TraitsResource current t6! ----- Method: TraitsTestCase>>tearDown (in category 'running') ----- tearDown | behaviorName | TraitsResource resetIfDirty. self createdClassesAndTraits do: [:aClassOrTrait | behaviorName := aClassOrTrait name. Smalltalk at: behaviorName ifPresent: [:classOrTrait | classOrTrait removeFromSystem]. ChangeSet current removeClassChanges: behaviorName]. createdClassesAndTraits := nil! ----- Method: TraitsTestCase>>testChangeSuperclass (in category 'testing-applying trait composition') ----- testChangeSuperclass "self run: #testChangeSuperclass" "Test that when the superclass of a class is changed the non-local methods of the class sending super are recompiled to correctly store the new superclass." | aC2 newSuperclass | aC2 := self c2 new. "C1 is current superclass of C2" self assert: aC2 m51. self assert: self c2 superclass == self c1. self deny: (self c2 localSelectors includes: #m51). "change superclass of C2 from C1 to X" newSuperclass := self createClassNamed: #TraitsTestX superclass: Object uses: {}. newSuperclass subclass: self c2 name uses: self c2 traitComposition instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: self c2 category. self assert: self c2 superclass == newSuperclass. newSuperclass compile: 'foo ^17'. self assert: aC2 m51 = 17. self deny: (self c2 localSelectors includes: #m51). self c2 compile: 'm51 ^19'. self assert: aC2 m51 = 19. "no sharing!!" self deny: (self c2 >> #m52) == (self t5 >> #m52).! |
Free forum by Nabble | Edit this page |