@@ -119,6 +119,76 @@ ActionChainArbitrary<String> xOrFailing() {
119
119
.withMaxTransformations (30 );
120
120
}
121
121
122
+ static class SetMutatingChainState {
123
+ final List <String > actualOps = new ArrayList <>();
124
+ final Set <Integer > set = new HashSet <>();
125
+
126
+ @ Override
127
+ public String toString () {
128
+ return "set=" + set + ", actualOps=" + actualOps ;
129
+ }
130
+ }
131
+
132
+ @ Property
133
+ void chainActionsAreProperlyDescribedEvenAfterChainExecution (@ ForAll ("setMutatingChain" ) ActionChain <SetMutatingChainState > chain ) {
134
+ SetMutatingChainState finalState = chain .run ();
135
+
136
+ assertThat (chain .transformations ())
137
+ .describedAs ("chain.transformations() should be the same as the list of operations in finalState.actualOps, final state is %s" , finalState .set )
138
+ .isEqualTo (finalState .actualOps );
139
+ }
140
+
141
+ @ Provide
142
+ public ActionChainArbitrary <SetMutatingChainState > setMutatingChain () {
143
+ return
144
+ ActionChain
145
+ .startWith (SetMutatingChainState ::new )
146
+ // This is an action that does not depend on the state to produce the transformation
147
+ .addAction (
148
+ 1 ,
149
+ Action .just ("clear anyway" , state -> {
150
+ state .actualOps .add ("clear anyway" );
151
+ state .set .clear ();
152
+ return state ;
153
+ })
154
+ )
155
+ // Below actions depend on the state to derive the transformations
156
+ .addAction (
157
+ 1 ,
158
+ (Action .Dependent <SetMutatingChainState >)
159
+ state ->
160
+ Arbitraries
161
+ .just (
162
+ state .set .isEmpty ()
163
+ ? Transformer .noop ()
164
+ : Transformer .<SetMutatingChainState >mutate ("clear " + state .set , set -> {
165
+ state .actualOps .add ("clear " + set .set );
166
+ state .set .clear ();
167
+ })
168
+ )
169
+ )
170
+ .addAction (
171
+ 2 ,
172
+ (Action .Dependent <SetMutatingChainState >)
173
+ state ->
174
+ Arbitraries
175
+ .integers ()
176
+ .between (1 , 10 )
177
+ .map (i -> {
178
+ if (state .set .contains (i )) {
179
+ return Transformer .noop ();
180
+ } else {
181
+ return Transformer .mutate ("add " + i + " to " + state .set , newState -> {
182
+ newState .actualOps .add ("add " + i + " to " + newState .set );
183
+ newState .set .add (i );
184
+ });
185
+ }
186
+ }
187
+ )
188
+ )
189
+ .withMaxTransformations (5 );
190
+ }
191
+
122
192
@ Property
123
193
void chainChoosesBetweenTwoActions (@ ForAll ("xOrY" ) ActionChain <String > chain ) {
124
194
String result = chain .run ();
0 commit comments