From 1507cc30b0c590a0e92337bb69073e1ae938110d Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 10:04:10 +0100 Subject: [PATCH 1/8] add test for FMMultiMultiValue --- .../FMMultiMultivalueLinkTest.class.st | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/Fame-Tests/FMMultiMultivalueLinkTest.class.st diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st new file mode 100644 index 00000000..5e59c37f --- /dev/null +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -0,0 +1,29 @@ +Class { + #name : #FMMultiMultivalueLinkTest, + #superclass : #TestCase, + #category : #'Fame-Tests-Core' +} + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneDragonIsKilledByOneHero [ + | dragon1 hero1 | + dragon1 := RPGDragon new. + hero1 := RPGHero new. + dragon1 killedBy: { hero1 }. + self assert: dragon1 killedBy size equals: 1. + self assert: dragon1 killedBy anyOne equals: hero1. +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testTwoDragonsAreKilledByOneHero [ + | dragon1 hero1 dragon2 | + dragon1 := RPGDragon new. + dragon2 := RPGDragon new. + hero1 := RPGHero new. + dragon1 killedBy: { hero1 }. + dragon2 killedBy: { hero1 }. + self assert: dragon1 killedBy size equals: 1. + self assert: dragon1 killedBy anyOne equals: hero1. + self assert: dragon2 killedBy size equals: 1. + self assert: dragon2 killedBy anyOne equals: hero1. +] From 6f78a1d9ddc3af3bddd2171ccc8000d75ea32466 Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 10:25:34 +0100 Subject: [PATCH 2/8] add several other tests --- src/Fame-Tests/FMDungeonExample.class.st | 5 + .../FMMultiMultivalueLinkTest.class.st | 111 +++++++++++++++++- 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/Fame-Tests/FMDungeonExample.class.st b/src/Fame-Tests/FMDungeonExample.class.st index e1f06575..b8a1b681 100644 --- a/src/Fame-Tests/FMDungeonExample.class.st +++ b/src/Fame-Tests/FMDungeonExample.class.st @@ -1,3 +1,8 @@ +" +This class contains tests. + +More tests dedicated to `FMMultiMultivalueLink` are in `FMMultiMultivalueLinkTest` +" Class { #name : #FMDungeonExample, #superclass : #TestCase, diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st index 5e59c37f..69076c69 100644 --- a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -1,3 +1,6 @@ +" +This class is complementary with the tests in `FMDungeonExample` +" Class { #name : #FMMultiMultivalueLinkTest, #superclass : #TestCase, @@ -6,24 +9,130 @@ Class { { #category : #tests } FMMultiMultivalueLinkTest >> testOneDragonIsKilledByOneHero [ + | dragon1 hero1 | dragon1 := RPGDragon new. hero1 := RPGHero new. dragon1 killedBy: { hero1 }. self assert: dragon1 killedBy size equals: 1. - self assert: dragon1 killedBy anyOne equals: hero1. + self assert: dragon1 killedBy anyOne equals: hero1 +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKillOneDragon [ + + | dragon1 hero1 | + dragon1 := RPGDragon new. + hero1 := RPGHero new. + hero1 kills: { dragon1 }. + self assert: hero1 kills size equals: 1. + self assert: hero1 kills anyOne equals: dragon1 +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKillTwiceTheSameDragon [ + + | dragon1 hero1 | + dragon1 := RPGDragon new. + hero1 := RPGHero new. + hero1 kills: { + dragon1. + dragon1 }. + self assert: hero1 kills size equals: 1. + self assert: hero1 kills anyOne equals: dragon1. + self assert: dragon1 killedBy size equals: 1. + self assert: dragon1 killedBy anyOne equals: hero1 +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKillTwoDragons [ + + | dragon1 dragon2 hero1 | + dragon1 := RPGDragon new. + dragon2 := RPGDragon new. + hero1 := RPGHero new. + hero1 kills: { + dragon1. + dragon2 }. + self assert: hero1 kills size equals: 2. + self assertCollection: hero1 kills hasSameElements: { + dragon1. + dragon2 } ] { #category : #tests } FMMultiMultivalueLinkTest >> testTwoDragonsAreKilledByOneHero [ + | dragon1 hero1 dragon2 | dragon1 := RPGDragon new. dragon2 := RPGDragon new. hero1 := RPGHero new. dragon1 killedBy: { hero1 }. dragon2 killedBy: { hero1 }. + "From dragon to hero relation" self assert: dragon1 killedBy size equals: 1. self assert: dragon1 killedBy anyOne equals: hero1. self assert: dragon2 killedBy size equals: 1. self assert: dragon2 killedBy anyOne equals: hero1. + "From hero to dragon relation" + self assert: hero1 kills size equals: 2. + self assertCollection: hero1 kills hasSameElements: { + dragon1. + dragon2 } +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testTwoDragonsAreKilledByTwoHeros [ + + | dragon1 hero1 dragon2 hero2 | + dragon1 := RPGDragon new. + dragon2 := RPGDragon new. + hero1 := RPGHero new. + hero2 := RPGHero new. + dragon1 killedBy: { + hero1. + hero2 }. + dragon2 killedBy: { + hero1. + hero2 }. + self assert: dragon1 killedBy size equals: 2. + self assertCollection: dragon1 killedBy hasSameElements: { + hero1. + hero2 }. + self assert: dragon2 killedBy size equals: 2. + self assertCollection: dragon2 killedBy hasSameElements: { + hero1. + hero2 }. + "From hero to dragon relation" + self assert: hero1 kills size equals: 2. + self assert: hero2 kills size equals: 2. + self assertCollection: hero1 kills hasSameElements: { + dragon1. + dragon2 }. + self assertCollection: hero2 kills hasSameElements: { + dragon1. + dragon2 } +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testTwoHerosKillTwiceTheSameDragon [ + + | dragon1 hero1 hero2 | + dragon1 := RPGDragon new. + hero1 := RPGHero new. + hero2 := RPGHero new. + hero1 kills: { + dragon1. + dragon1 }. + hero2 kills: { + dragon1. + dragon1 }. + self assert: hero1 kills size equals: 1. + self assert: hero1 kills anyOne equals: dragon1. + self assert: hero2 kills size equals: 1. + self assert: hero2 kills anyOne equals: dragon1. + self assert: dragon1 killedBy size equals: 2. + self assertCollection: dragon1 killedBy hasSameElements: { + hero1. + hero2 } ] From 5eb3987dce1b056208498eb1cdda793efc8df01f Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 10:33:25 +0100 Subject: [PATCH 3/8] add tests when adding several times several elements --- .../FMMultiMultivalueLinkTest.class.st | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st index 69076c69..5b6ae1ef 100644 --- a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -114,6 +114,63 @@ FMMultiMultivalueLinkTest >> testTwoDragonsAreKilledByTwoHeros [ dragon2 } ] +{ #category : #tests } +FMMultiMultivalueLinkTest >> testTwoHerosKillTWiceTwoDragons [ + + | dragon1 dragon2 hero1 hero2 | + dragon1 := RPGDragon new. + dragon2 := RPGDragon new. + hero1 := RPGHero new. + hero2 := RPGHero new. + hero1 kills: { + dragon1. + dragon1. + dragon2. + dragon2 }. + hero2 kills: { + dragon1. + dragon1. + dragon2. + dragon2 }. + self assert: hero1 kills size equals: 2. + self assert: hero1 kills anyOne equals: dragon1. + self assert: hero2 kills size equals: 2. + self assert: hero2 kills anyOne equals: dragon1. + self assert: dragon1 killedBy size equals: 2. + self assertCollection: dragon1 killedBy hasSameElements: { + hero1. + hero2 }. + self assert: dragon2 killedBy size equals: 2. + self assertCollection: dragon2 killedBy hasSameElements: { + hero1. + hero2 } +] + +{ #category : #tests } +FMMultiMultivalueLinkTest >> testTwoHerosKillThriceTheSameDragon [ + + | dragon1 hero1 hero2 | + dragon1 := RPGDragon new. + hero1 := RPGHero new. + hero2 := RPGHero new. + hero1 kills: { + dragon1. + dragon1 }. + hero1 kills add: dragon1. + hero2 kills: { + dragon1. + dragon1 }. + hero2 kills add: dragon1. + self assert: hero1 kills size equals: 1. + self assert: hero1 kills anyOne equals: dragon1. + self assert: hero2 kills size equals: 1. + self assert: hero2 kills anyOne equals: dragon1. + self assert: dragon1 killedBy size equals: 2. + self assertCollection: dragon1 killedBy hasSameElements: { + hero1. + hero2 } +] + { #category : #tests } FMMultiMultivalueLinkTest >> testTwoHerosKillTwiceTheSameDragon [ From 62d93f50ed09e21643f5d8405c2b67bdf938c118 Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 10:47:24 +0100 Subject: [PATCH 4/8] add more tests for more combinaison --- .../FMMultiMultivalueLinkTest.class.st | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st index 5b6ae1ef..f75451b1 100644 --- a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -29,6 +29,23 @@ FMMultiMultivalueLinkTest >> testOneHeroKillOneDragon [ self assert: hero1 kills anyOne equals: dragon1 ] +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKillOneDragonsThenTwoWithTheFirstOneAgain [ + + | dragon1 dragon2 hero1 | + dragon1 := RPGDragon new. + dragon2 := RPGDragon new. + hero1 := RPGHero new. + hero1 kills: { dragon1 }. + hero1 kills: { + dragon1. + dragon2 }. + self assert: hero1 kills size equals: 2. + self assertCollection: hero1 kills hasSameElements: { + dragon1. + dragon2 } +] + { #category : #tests } FMMultiMultivalueLinkTest >> testOneHeroKillTwiceTheSameDragon [ @@ -60,6 +77,19 @@ FMMultiMultivalueLinkTest >> testOneHeroKillTwoDragons [ dragon2 } ] +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKilledLotOfDragon [ + + "This is a performance test" + + | dragons hero1 | + dragons := OrderedCollection new. + 1 to: 50000 do: [ :index | dragons add: RPGDragon new ]. + hero1 := RPGHero new. + hero1 kills: dragons. + self assert: hero1 kills size equals: 50000. +] + { #category : #tests } FMMultiMultivalueLinkTest >> testTwoDragonsAreKilledByOneHero [ From 5695b8d433163ac5b87bd90e705409a908d9ea31 Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 10:56:08 +0100 Subject: [PATCH 5/8] enrich test with strange combinaison of adding. add uncheckAdd: methods based of noheckMethod and use them in value: for performance --- src/Fame-Core/FMMultiMultivalueLink.class.st | 8 ++++++++ src/Fame-Core/FMMultivalueLink.class.st | 4 ++-- src/Fame-Tests/FMMultiMultivalueLinkTest.class.st | 7 ++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Fame-Core/FMMultiMultivalueLink.class.st b/src/Fame-Core/FMMultiMultivalueLink.class.st index e65e3bb4..7d9f7c23 100644 --- a/src/Fame-Core/FMMultiMultivalueLink.class.st +++ b/src/Fame-Core/FMMultiMultivalueLink.class.st @@ -45,6 +45,14 @@ FMMultiMultivalueLink >> removeAll [ do: [ :anElement | (anElement perform: opposite) remove: owner ] ] +{ #category : #adding } +FMMultiMultivalueLink >> value: aCollection [ + + ^ self + removeAll: values copy; + uncheckAddAll: aCollection asOrderedCollection removeDuplicates +] + { #category : #private } FMMultiMultivalueLink >> with: element opposite: oppositeSelector [ self assert: oppositeSelector numArgs = 0. diff --git a/src/Fame-Core/FMMultivalueLink.class.st b/src/Fame-Core/FMMultivalueLink.class.st index 68658688..aa8ab75f 100644 --- a/src/Fame-Core/FMMultivalueLink.class.st +++ b/src/Fame-Core/FMMultivalueLink.class.st @@ -75,7 +75,7 @@ FMMultivalueLink >> = otherCollection [ ^ values hasEqualElements: otherCollection asOrderedCollection ] -{ #category : #accessing } +{ #category : #adding } FMMultivalueLink >> add: anElement [ anElement perform: opposite with: owner. self unsafeAdd: anElement. @@ -204,7 +204,7 @@ FMMultivalueLink >> unsafeRemove: element [ values remove: element ifAbsent: nil ] -{ #category : #accessing } +{ #category : #adding } FMMultivalueLink >> value: aCollection [ ^self removeAll: values copy; addAll: aCollection diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st index f75451b1..70e817d1 100644 --- a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -43,7 +43,12 @@ FMMultiMultivalueLinkTest >> testOneHeroKillOneDragonsThenTwoWithTheFirstOneAgai self assert: hero1 kills size equals: 2. self assertCollection: hero1 kills hasSameElements: { dragon1. - dragon2 } + dragon2 }. + + self assert: dragon1 killedBy size equals: 1. + self assert: dragon2 killedBy size equals: 1. + self assert: dragon1 killedBy anyOne equals: hero1. + self assert: dragon2 killedBy anyOne equals: hero1 ] { #category : #tests } From 9199b660434ddfaec005d6126df2ccc466792ca4 Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 10:56:40 +0100 Subject: [PATCH 6/8] add this --- src/Fame-Core/FMMultiMultivalueLink.class.st | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Fame-Core/FMMultiMultivalueLink.class.st b/src/Fame-Core/FMMultiMultivalueLink.class.st index 7d9f7c23..a6f721d1 100644 --- a/src/Fame-Core/FMMultiMultivalueLink.class.st +++ b/src/Fame-Core/FMMultiMultivalueLink.class.st @@ -45,6 +45,26 @@ FMMultiMultivalueLink >> removeAll [ do: [ :anElement | (anElement perform: opposite) remove: owner ] ] +{ #category : #'private - adding' } +FMMultiMultivalueLink >> uncheckAdd: anElement [ + (anElement perform: opposite) uncheckUnsafeAdd: owner. + values add: anElement. + ^ anElement +] + +{ #category : #'private - adding' } +FMMultiMultivalueLink >> uncheckAddAll: aCollection [ + "Include all the elements of aCollection as the receiver's elements. Answer + aCollection. Actually, any object responding to #do: can be used as argument." + aCollection do: [ :each | self uncheckAdd: each ]. + ^ aCollection +] + +{ #category : #'private - adding' } +FMMultiMultivalueLink >> uncheckUnsafeAdd: element [ + values add: element +] + { #category : #adding } FMMultiMultivalueLink >> value: aCollection [ From aca33910010334d37760364dc5b5d9fad243c6d9 Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 11:04:44 +0100 Subject: [PATCH 7/8] Add a test that ensure that the removeAll feature still works well --- .../FMMultiMultivalueLinkTest.class.st | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st index 70e817d1..10583533 100644 --- a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -82,6 +82,24 @@ FMMultiMultivalueLinkTest >> testOneHeroKillTwoDragons [ dragon2 } ] +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKillTwoDragonsAndFinallyOnlyOne [ + + | dragon1 dragon2 hero1 | + dragon1 := RPGDragon new. + dragon2 := RPGDragon new. + hero1 := RPGHero new. + hero1 kills: { + dragon1. + dragon2 }. + hero1 kills: { dragon1 }. + self assert: hero1 kills size equals: 1. + self assertCollection: hero1 kills hasSameElements: { dragon1 }. + self assert: dragon1 killedBy size equals: 1. + self assert: dragon1 killedBy anyOne equals: hero1. + self assert: dragon2 killedBy size equals: 0 +] + { #category : #tests } FMMultiMultivalueLinkTest >> testOneHeroKilledLotOfDragon [ From 2bc55010237fe6379f0f224cbce01a091d155a47 Mon Sep 17 00:00:00 2001 From: badetitou Date: Sat, 18 Mar 2023 11:06:05 +0100 Subject: [PATCH 8/8] dragon can revive --- src/Fame-Tests/FMMultiMultivalueLinkTest.class.st | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st index 10583533..305d1cc9 100644 --- a/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st +++ b/src/Fame-Tests/FMMultiMultivalueLinkTest.class.st @@ -29,6 +29,18 @@ FMMultiMultivalueLinkTest >> testOneHeroKillOneDragon [ self assert: hero1 kills anyOne equals: dragon1 ] +{ #category : #tests } +FMMultiMultivalueLinkTest >> testOneHeroKillOneDragonThenTheDragonDecideToNotBeKilled [ + + | dragon1 hero1 | + dragon1 := RPGDragon new. + hero1 := RPGHero new. + hero1 kills: { dragon1 }. + dragon1 killedBy: { }. + self assert: hero1 kills size equals: 0. + self assert: dragon1 killedBy size equals: 0 +] + { #category : #tests } FMMultiMultivalueLinkTest >> testOneHeroKillOneDragonsThenTwoWithTheFirstOneAgain [