Skip to content

Commit cfbb458

Browse files
committed
fix: Safely remove entry from the cache.
1 parent 8dad0df commit cfbb458

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

src/main/java/io/github/nstdio/http/ext/LruMultimap.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ V remove(K k, ToIntFunction<List<V>> idxFn) {
133133
List<V> vs = m.get(k);
134134

135135
V v = null;
136-
int i = idxFn.applyAsInt(vs);
137-
if (i != -1) {
136+
int i;
137+
if (vs != null && (i = idxFn.applyAsInt(vs)) >= 0 && i < vs.size()) {
138138
v = vs.remove(i);
139139
notifyEvicted(v);
140140
size--;

src/test/kotlin/io/github/nstdio/http/ext/LruMultimapTest.kt

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@
1717
package io.github.nstdio.http.ext
1818

1919
import io.github.nstdio.http.ext.Assertions.assertThat
20+
import io.kotest.matchers.nulls.shouldBeNull
21+
import io.kotest.matchers.shouldBe
2022
import org.assertj.core.api.Assertions.assertThat
2123
import org.junit.jupiter.api.Assertions.assertFalse
2224
import org.junit.jupiter.api.Assertions.assertTrue
2325
import org.junit.jupiter.api.Test
2426
import org.mockito.Mockito
27+
import org.mockito.Mockito.mock
2528
import org.mockito.Mockito.verify
29+
import org.mockito.Mockito.verifyNoInteractions
2630
import org.mockito.Mockito.verifyNoMoreInteractions
2731
import java.util.function.Consumer
2832
import java.util.function.ToIntFunction
@@ -180,7 +184,7 @@ class LruMultimapTest {
180184

181185
//then
182186
assertThat(map).isEmpty
183-
Mockito.verifyNoInteractions(mockEl)
187+
verifyNoInteractions(mockEl)
184188
}
185189

186190
@Test
@@ -217,7 +221,7 @@ class LruMultimapTest {
217221
}
218222

219223
@Suppress("UNCHECKED_CAST")
220-
private fun mockConsumer() = Mockito.mock(Consumer::class.java) as Consumer<String?>
224+
private fun mockConsumer() = mock(Consumer::class.java) as Consumer<String?>
221225

222226
@Test
223227
fun shouldEvictAllForNonExistingKey() {
@@ -232,6 +236,27 @@ class LruMultimapTest {
232236

233237
//then
234238
assertThat(map).hasMapSize(1).hasSize(2)
235-
Mockito.verifyNoInteractions(mockEl)
239+
verifyNoInteractions(mockEl)
240+
}
241+
242+
@Test
243+
fun `Should remove`() {
244+
//given
245+
val map = LruMultimap<String, String>(8, null)
246+
val nonExistingKeyFn = mock(ToIntFunction::class.java) as ToIntFunction<List<String>>
247+
248+
//when
249+
map.putSingle("a", "1", addFn)
250+
map.putSingle("a", "2", addFn)
251+
map.putSingle("b", "2", addFn)
252+
253+
254+
//then
255+
map.remove("a") { 2 }.shouldBeNull()
256+
map.remove("a") { -1 }.shouldBeNull()
257+
map.remove("a") { 0 }.shouldBe("2")
258+
map.remove("b") { 0 }.shouldBe("2")
259+
map.remove("c", nonExistingKeyFn).shouldBeNull()
260+
verifyNoInteractions(nonExistingKeyFn)
236261
}
237262
}

0 commit comments

Comments
 (0)