Skip to content

Commit 87d9e53

Browse files
authored
Merge pull request #41 from ba-st/multiple_swap
SystemHotSwapper swapping several systems at once
2 parents 4df264e + 896cea6 commit 87d9e53

File tree

4 files changed

+191
-40
lines changed

4 files changed

+191
-40
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"
2+
I'm a system implementation failing when trying to add a customer. Used for testing purposes.
3+
"
4+
Class {
5+
#name : #FixedCustomerManagementSystem,
6+
#superclass : #SubsystemImplementation,
7+
#category : #'Kepler-System-Tests'
8+
}
9+
10+
{ #category : #API }
11+
FixedCustomerManagementSystem >> addCustomer: aCustomer [
12+
13+
SystemCommandExecutionError signal: 'Cannot add customer'
14+
]
15+
16+
{ #category : #installing }
17+
FixedCustomerManagementSystem >> dependencies [
18+
19+
^ #()
20+
]
21+
22+
{ #category : #installing }
23+
FixedCustomerManagementSystem >> implementedInterfaces [
24+
25+
^ #(#CustomerManagementSystem)
26+
]
27+
28+
{ #category : #installing }
29+
FixedCustomerManagementSystem >> name [
30+
31+
^ 'CMS'
32+
]

source/Kepler-System-Tests/SystemHotSwapperTest.class.st

+114-24
Original file line numberDiff line numberDiff line change
@@ -4,73 +4,163 @@ SystemHotSwapper test case
44
Class {
55
#name : #SystemHotSwapperTest,
66
#superclass : #TestCase,
7+
#instVars : [
8+
'composite'
9+
],
710
#category : #'Kepler-System-Tests'
811
}
912

10-
{ #category : #tests }
11-
SystemHotSwapperTest >> testCantSwapWhenTheInterfaceIsNotImplemented [
13+
{ #category : #private }
14+
SystemHotSwapperTest >> assert: aSubsystem implements: anInterfaceKey [
1215

13-
| composite cms newCMS |
16+
self assert: ( self is: anInterfaceKey implementedBy: aSubsystem )
17+
]
1418

15-
cms := SampleCustomerSystem new.
19+
{ #category : #private }
20+
SystemHotSwapperTest >> deny: aSubsystem implements: anInterfaceKey [
21+
22+
self deny: ( self is: anInterfaceKey implementedBy: aSubsystem )
23+
]
24+
25+
{ #category : #private }
26+
SystemHotSwapperTest >> is: anInterfaceKey implementedBy: aSubsystem [
27+
28+
^ aSubsystem implements: ( composite interfaceAt: anInterfaceKey )
29+
]
30+
31+
{ #category : #running }
32+
SystemHotSwapperTest >> setUp [
33+
34+
super setUp.
1635
composite := CompositeSystem new
17-
register: cms;
18-
yourself.
19-
composite startUp.
36+
]
2037

21-
newCMS := FixedCustomerSystem new.
38+
{ #category : #running }
39+
SystemHotSwapperTest >> tearDown [
40+
41+
composite shutDown.
42+
super tearDown
43+
]
44+
45+
{ #category : #tests }
46+
SystemHotSwapperTest >> testCantSwapWhenTheInterfaceIsNotImplemented [
47+
48+
composite
49+
register: SampleCustomerSystem new;
50+
startUp.
2251

2352
self
24-
should: [ (SystemHotSwapper swapSystemImplementing: #CustomerManagementSystem with: newCMS) applyTo: composite ]
53+
should: [ SystemHotSwapper swapSystemImplementing: #CustomerManagementSystem with: FixedCustomerSystem new ]
2554
raise: SystemControlError
2655
withMessageText: 'CMS is not implementing Customer Management'
2756
]
2857

2958
{ #category : #tests }
3059
SystemHotSwapperTest >> testSwapping [
3160

32-
| composite cms newCMS |
61+
| cms newCMS |
3362

3463
cms := SampleCustomerSystem new.
35-
composite := CompositeSystem new
64+
composite
3665
register: cms;
37-
yourself.
38-
composite startUp.
66+
startUp.
3967

4068
cms addCustomer: 'John'.
4169

4270
newCMS := FixedCustomerSystem new.
4371

44-
self deny: cms = newCMS.
45-
4672
self
4773
assert: composite >> #CustomerQueryingSystem equals: cms;
48-
assert: (composite >> #CustomerQueryingSystem) customers size equals: 1.
74+
assert: ( composite >> #CustomerQueryingSystem ) customers size equals: 1.
4975

50-
(SystemHotSwapper swapSystemImplementing: #CustomerQueryingSystem with: newCMS) applyTo: composite.
76+
( SystemHotSwapper swapSystemImplementing: #CustomerQueryingSystem with: newCMS )
77+
applyTo: composite.
5178

5279
self
5380
assert: composite >> #CustomerQueryingSystem equals: newCMS;
54-
assert: (composite >> #CustomerQueryingSystem) customers size equals: 2
81+
assert: ( composite >> #CustomerQueryingSystem ) customers size equals: 2
82+
]
83+
84+
{ #category : #tests }
85+
SystemHotSwapperTest >> testSwappingFailedWhenReplacementsAreMissingSomeInterfaces [
86+
87+
| cms pms swapper |
88+
89+
cms := SampleCustomerSystem new.
90+
pms := SampleProjectSystem new.
91+
composite
92+
register: cms;
93+
register: pms;
94+
startUp.
95+
96+
self
97+
assert: composite >> #CustomerManagementSystem equals: cms;
98+
assert: pms >> #CustomerQueryingSystem equals: cms.
99+
100+
swapper := SystemHotSwapper
101+
swapSystemImplementing: #CustomerManagementSystem
102+
with: FixedCustomerManagementSystem new.
103+
104+
self
105+
should: [ swapper applyTo: composite ]
106+
raise: SystemControlError
107+
withMessageText: 'System implementing "Customer Querying" not found.'
108+
]
109+
110+
{ #category : #tests }
111+
SystemHotSwapperTest >> testSwappingOneImplementationWithTwoOthers [
112+
113+
"This test checks that a system implementing more than one interface can be replaced
114+
by two or more systems implementing the required interfaces"
115+
116+
| cms managementSystem queryingSystem |
117+
118+
cms := SampleCustomerSystem new.
119+
composite
120+
register: cms;
121+
startUp.
122+
123+
self
124+
assert: cms implements: #CustomerQueryingSystem;
125+
assert: cms implements: #CustomerManagementSystem.
126+
127+
managementSystem := FixedCustomerManagementSystem new.
128+
self
129+
assert: managementSystem implements: #CustomerManagementSystem;
130+
deny: managementSystem implements: #CustomerQueryingSystem.
131+
132+
queryingSystem := FixedCustomerSystem new.
133+
self
134+
assert: queryingSystem implements: #CustomerQueryingSystem;
135+
deny: queryingSystem implements: #CustomerManagementSystem.
136+
137+
self
138+
assert: composite >> #CustomerQueryingSystem equals: cms;
139+
assert: composite >> #CustomerManagementSystem equals: cms.
140+
141+
( SystemHotSwapper
142+
swapSystemImplementingAll: #(#CustomerQueryingSystem #CustomerManagementSystem)
143+
with: ( Array with: queryingSystem with: managementSystem ) ) applyTo: composite.
144+
145+
self
146+
assert: composite >> #CustomerQueryingSystem equals: queryingSystem;
147+
assert: composite >> #CustomerManagementSystem equals: managementSystem
55148
]
56149

57150
{ #category : #tests }
58151
SystemHotSwapperTest >> testSwappingSystemWithDependents [
59152

60-
| composite cms newCMS pms |
153+
| cms newCMS pms |
61154

62155
cms := SampleCustomerSystem new.
63156
pms := SampleProjectSystem new.
64-
composite := CompositeSystem new
157+
composite
65158
register: cms;
66159
register: pms;
67-
yourself.
68-
composite startUp.
160+
startUp.
69161

70162
newCMS := FixedCustomerSystem new.
71163

72-
self deny: cms = newCMS.
73-
74164
self
75165
assert: composite >> #CustomerQueryingSystem equals: cms;
76166
assert: pms >> #CustomerQueryingSystem equals: cms.

source/Kepler-System/SystemHotInstaller.class.st

+15-6
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,36 @@ Class {
55
#name : #SystemHotInstaller,
66
#superclass : #Object,
77
#instVars : [
8-
'subsystem'
8+
'subsystems'
99
],
1010
#category : #'Kepler-System'
1111
}
1212

1313
{ #category : #'instance creation' }
1414
SystemHotInstaller class >> installing: aSubsystem [
1515

16-
^self new initializeInstalling: aSubsystem
16+
^ self installingAll: {aSubsystem}
17+
]
18+
19+
{ #category : #'instance creation' }
20+
SystemHotInstaller class >> installingAll: aSubsystemCollection [
21+
22+
^self new initializeInstallingAll: aSubsystemCollection
1723
]
1824

1925
{ #category : #applying }
2026
SystemHotInstaller >> applyTo: aCompositeSystem [
2127

22-
aCompositeSystem register: subsystem.
23-
subsystem startUp.
28+
subsystems
29+
do: [ :subsystem |
30+
aCompositeSystem register: subsystem.
31+
subsystem startUp
32+
].
2433
aCompositeSystem resolveSubsystemDependencies
2534
]
2635

2736
{ #category : #initialization }
28-
SystemHotInstaller >> initializeInstalling: aSubsystem [
37+
SystemHotInstaller >> initializeInstallingAll: aSubsystemCollection [
2938

30-
subsystem := aSubsystem
39+
subsystems := aSubsystemCollection
3140
]

source/Kepler-System/SystemHotSwapper.class.st

+30-10
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ Class {
55
#name : #SystemHotSwapper,
66
#superclass : #Object,
77
#instVars : [
8-
'subsystem',
9-
'interfaceKey'
8+
'interfaceKey',
9+
'subsystems'
1010
],
1111
#pools : [
1212
'Kepler'
@@ -15,17 +15,37 @@ Class {
1515
}
1616

1717
{ #category : #'private - preconditions' }
18-
SystemHotSwapper class >> assert: aSubsystem implements: anInterfaceKey [
18+
SystemHotSwapper class >> assert: aSubsystem implementsAnyIn: anInterfaceKeyCollection [
1919

20-
(SystemInterfaces >> anInterfaceKey isImplementedBy: aSubsystem)
21-
ifFalse: [ SystemControlError signal: ('<1p> is not implementing <2p>' expandMacrosWith: aSubsystem with: SystemInterfaces >> anInterfaceKey) ]
20+
anInterfaceKeyCollection
21+
detect: [ :anInterfaceKey | SystemInterfaces >> anInterfaceKey isImplementedBy: aSubsystem ]
22+
ifNone: [ SystemControlError
23+
signal:
24+
( '<1p> is not implementing <2s>'
25+
expandMacrosWith: aSubsystem
26+
with:
27+
( ( CollectionFormatter
28+
separatingWith: $,
29+
applyingToEach: [ :anInterfaceKey | ( SystemInterfaces >> anInterfaceKey ) printString ] )
30+
format: anInterfaceKeyCollection ) )
31+
]
2232
]
2333

2434
{ #category : #'instance creation' }
2535
SystemHotSwapper class >> swapSystemImplementing: anInterfaceKey with: aSubsystem [
2636

27-
self assert: aSubsystem implements: anInterfaceKey.
28-
^self new initializeSwapSystemImplementing: anInterfaceKey with: aSubsystem
37+
^ self swapSystemImplementingAll: {anInterfaceKey} with: {aSubsystem}
38+
]
39+
40+
{ #category : #'instance creation' }
41+
SystemHotSwapper class >> swapSystemImplementingAll: anInterfaceKeyCollection with: aSubsystemCollection [
42+
43+
aSubsystemCollection
44+
do: [ :aSubsystem | self assert: aSubsystem implementsAnyIn: anInterfaceKeyCollection ].
45+
46+
^ self new
47+
initializeSwapSystemImplementing: anInterfaceKeyCollection anyOne
48+
withAll: aSubsystemCollection
2949
]
3050

3151
{ #category : #applying }
@@ -36,12 +56,12 @@ SystemHotSwapper >> applyTo: aCompositeSystem [
3656
subsystemToSwap := aCompositeSystem >> interfaceKey.
3757
subsystemToSwap shutDown.
3858
aCompositeSystem unregister: subsystemToSwap.
39-
(SystemHotInstaller installing: subsystem) applyTo: aCompositeSystem
59+
( SystemHotInstaller installingAll: subsystems ) applyTo: aCompositeSystem
4060
]
4161

4262
{ #category : #initialization }
43-
SystemHotSwapper >> initializeSwapSystemImplementing: anInterfaceKey with: aSubsystem [
63+
SystemHotSwapper >> initializeSwapSystemImplementing: anInterfaceKey withAll: aSubsystemCollection [
4464

4565
interfaceKey := anInterfaceKey.
46-
subsystem := aSubsystem
66+
subsystems := aSubsystemCollection
4767
]

0 commit comments

Comments
 (0)