1212
1313use PHPUnit_Framework_MockObject_MockObject as MockObject ;
1414use BadMethodCallException ;
15+ use RuntimeException ;
1516
1617use function Functional \memoize ;
1718
@@ -123,7 +124,6 @@ public function testMemoizeWithCustomKey()
123124
124125 $ this ->assertSame ('FOO BAR ' , memoize ([$ this ->callback , 'execute ' ], ['FOO ' , 'BAR ' ], 'MY:CUSTOM:KEY ' ));
125126 $ this ->assertSame ('FOO BAR ' , memoize ([$ this ->callback , 'execute ' ], ['BAR ' , 'BAZ ' ], 'MY:CUSTOM:KEY ' ), 'Result already memoized ' );
126- $ this ->assertSame ('FOO BAR ' , memoize ([$ this ->callback , 'execute ' ], ['BAR ' , 'BAZ ' ], ['MY ' , 'CUSTOM ' , 'KEY ' ]), 'Result already memoized ' );
127127
128128 $ this ->assertSame ('BAR BAZ ' , memoize ([$ this ->callback , 'execute ' ], ['BAR ' , 'BAZ ' ], 'MY:DIFFERENT:KEY ' ));
129129 $ this ->assertSame ('BAR BAZ ' , memoize ([$ this ->callback , 'execute ' ], ['BAR ' , 'BAZ ' ], 'MY:DIFFERENT:KEY ' ), 'Result already memoized ' );
@@ -150,25 +150,6 @@ public function testResultIsNotStoredIfExceptionIsThrown()
150150 }
151151 }
152152
153- public function testPassKeyGeneratorCallable ()
154- {
155- $ this ->callback
156- ->expects ($ this ->exactly (2 ))
157- ->method ('execute ' );
158-
159- $ keyGenerator = function () {
160- static $ index ;
161- return ($ index ++ % 2 ) === 0 ;
162- };
163-
164- memoize ([$ this ->callback , 'execute ' ], $ keyGenerator );
165- memoize ([$ this ->callback , 'execute ' ], [], $ keyGenerator );
166- memoize ([$ this ->callback , 'execute ' ], [], $ keyGenerator );
167- memoize ([$ this ->callback , 'execute ' ], $ keyGenerator );
168- memoize ([$ this ->callback , 'execute ' ], $ keyGenerator );
169- memoize ([$ this ->callback , 'execute ' ], [], $ keyGenerator );
170- }
171-
172153 public function testResetByPassingNullAsCallable ()
173154 {
174155 $ this ->callback
@@ -189,4 +170,62 @@ public function testPassNoCallable()
189170 $ this ->expectArgumentError ('Argument 1 passed to Functional\memoize() must be callable ' );
190171 memoize ('invalidFunction ' );
191172 }
173+
174+ public function testSplObjectHashCollisions ()
175+ {
176+ self ::assertSame (0 , memoize (self ::createFn (0 , 1 )));
177+ self ::assertSame (1 , memoize (self ::createFn (1 , 1 )));
178+ self ::assertSame (2 , memoize (self ::createFn (2 , 1 )));
179+ }
180+
181+ private static function createFn (int $ id , int $ number ): callable
182+ {
183+ return new class ($ id , $ number ) {
184+ private $ id ;
185+ private $ expectedInvocations ;
186+ private $ actualInvocations = 0 ;
187+
188+ public function __construct (int $ id , int $ expectedInvocations )
189+ {
190+ $ this ->id = $ id ;
191+ $ this ->expectedInvocations = $ expectedInvocations ;
192+ }
193+
194+ public function getId (): int
195+ {
196+ return $ this ->id ;
197+ }
198+
199+ public function __invoke (): int
200+ {
201+ $ this ->actualInvocations ++;
202+ if ($ this ->actualInvocations > $ this ->expectedInvocations ) {
203+ throw new RuntimeException (
204+ sprintf (
205+ 'ID %d: Expected %d invocations, got %d ' ,
206+ $ this ->id ,
207+ $ this ->expectedInvocations ,
208+ $ this ->actualInvocations
209+ )
210+ );
211+ }
212+
213+ return $ this ->id ;
214+ }
215+
216+ public function __destruct ()
217+ {
218+ if ($ this ->actualInvocations !== $ this ->expectedInvocations ) {
219+ throw new RuntimeException (
220+ sprintf (
221+ 'ID %d: Expected %d invocations, got %d ' ,
222+ $ this ->id ,
223+ $ this ->expectedInvocations ,
224+ $ this ->actualInvocations
225+ )
226+ );
227+ }
228+ }
229+ };
230+ }
192231}
0 commit comments