11package com .bobocode .cs ;
22
3- import lombok .SneakyThrows ;
4- import org .junit .jupiter .api .ClassOrderer .OrderAnnotation ;
5- import org .junit .jupiter .api .*;
6- import org .mockito .Mockito ;
3+ import static java .lang .reflect .Modifier .isStatic ;
4+ import static org .assertj .core .api .Assertions .assertThat ;
5+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
6+ import static org .junit .jupiter .api .Assertions .assertEquals ;
7+ import static org .junit .jupiter .api .Assertions .assertFalse ;
8+ import static org .junit .jupiter .api .Assertions .assertNull ;
9+ import static org .junit .jupiter .api .Assertions .assertTrue ;
710
811import java .lang .reflect .Field ;
912import java .util .Arrays ;
1215import java .util .concurrent .ThreadLocalRandom ;
1316import java .util .stream .Collectors ;
1417import java .util .stream .Stream ;
15-
16- import static java .lang .reflect .Modifier .isStatic ;
17- import static org .assertj .core .api .Assertions .assertThat ;
18- import static org .assertj .core .api .Assertions .assertThatThrownBy ;
19- import static org .junit .jupiter .api .Assertions .*;
20- import static org .mockito .Mockito .*;
18+ import lombok .SneakyThrows ;
19+ import org .junit .jupiter .api .ClassOrderer .OrderAnnotation ;
20+ import org .junit .jupiter .api .DisplayName ;
21+ import org .junit .jupiter .api .MethodOrderer ;
22+ import org .junit .jupiter .api .Nested ;
23+ import org .junit .jupiter .api .Order ;
24+ import org .junit .jupiter .api .Test ;
25+ import org .junit .jupiter .api .TestClassOrder ;
26+ import org .junit .jupiter .api .TestMethodOrder ;
2127
2228/**
2329 * A Reflection-based step by step test for a {@link HashTable} class. PLEASE NOTE that Reflection API should not be used
2834@ TestClassOrder (OrderAnnotation .class )
2935@ DisplayName ("HashTable Test" )
3036class HashTableTest {
37+
3138 private HashTable <String , Integer > hashTable = new HashTable <>();
3239
3340 @ Nested
@@ -126,6 +133,7 @@ void nodeConstructorAcceptKeyValue() {
126133 @ DisplayName ("2. HashTable fields Test" )
127134 @ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
128135 class HashTableFieldsTest {
136+
129137 @ Test
130138 @ Order (1 )
131139 @ DisplayName ("HastTable has a field 'table' which is an array of nodes" )
@@ -155,6 +163,7 @@ void sizeFieldExists() {
155163 @ DisplayName ("3. HashTable constructors Test" )
156164 @ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
157165 class HashTableConstructorsTest {
166+
158167 @ Test
159168 @ Order (1 )
160169 @ SneakyThrows
@@ -198,6 +207,7 @@ void constructorWithTableCapacityWhenArgumentIsNegative() {
198207 @ DisplayName ("4. Hash Function Test" )
199208 @ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
200209 class HashFunctionTest {
210+
201211 @ Test
202212 @ Order (1 )
203213 @ DisplayName ("calculateIndex returns the same value for the same key" )
@@ -221,8 +231,8 @@ void calculateIndexReturnDifferentValuesWheKeysAreDifferent() {
221231
222232 assertThat (indexSet )
223233 .hasSizeGreaterThan (1 );
224- }
225-
234+ }
235+
226236 @ Test
227237 @ Order (3 )
228238 @ DisplayName ("calculateIndex returns values in array bounds" )
@@ -235,7 +245,7 @@ void calculateIndexReturnIndexInArrayBounds() {
235245 var indexes = keys .stream ()
236246 .map (key -> HashTable .calculateIndex (key , arrayCapacity ))
237247 .toList ();
238-
248+
239249 assertThat (indexes )
240250 .isNotEmpty ()
241251 .allMatch (i -> i >= 0 && i < arrayCapacity );
@@ -262,19 +272,20 @@ class HashTableMethodsTest {
262272 @ Test
263273 @ SneakyThrows
264274 @ Order (1 )
265- @ DisplayName ("put creates new entry and returns null when the table is empty" )
275+ @ DisplayName ("put creates new entry and returns null when the table is empty, should increase the table size " )
266276 void putWhenTableIsEmpty () {
267277 var previousValue = hashTable .put ("madmax" , 833 );
268278
269279 var keyValueExists = checkKeyValueExists ("madmax" , 833 );
270280
271281 assertNull (previousValue );
272282 assertTrue (keyValueExists );
283+ assertEquals (1 , getSize ());
273284 }
274285
275286 @ Test
276287 @ Order (2 )
277- @ DisplayName ("put elements adds entry to to the same bucket when the hash code is the same" )
288+ @ DisplayName ("put elements adds entry to the same bucket and increases table size when the hash code is the same" )
278289 @ SneakyThrows
279290 void putTwoElementsWithTheSameHashCode () {
280291 var table = getInternalTable (hashTable );
@@ -290,11 +301,13 @@ void putTwoElementsWithTheSameHashCode() {
290301 assertTrue (containsKeyValueA );
291302 assertTrue (containsKeyValueB );
292303 assertThat (bucketIndexA ).isEqualTo (bucketIndexB );
304+ assertEquals (2 , getSize ());
293305 }
294306
295307 @ Test
296308 @ Order (3 )
297- @ DisplayName ("put element updates the value and returns the previous one when key is the same" )
309+ @ DisplayName (
310+ "put element updates the value and returns the previous one when key is the same, should not increase table size" )
298311 void putElementWithTheSameKey () {
299312 hashTable .put ("madmax" , 833 );
300313 System .out .println (hashTable );
@@ -305,6 +318,7 @@ void putElementWithTheSameKey() {
305318
306319 assertThat (previousValue ).isEqualTo (833 );
307320 assertTrue (containsNewValueByKey );
321+ assertEquals (1 , getSize ());
308322 }
309323
310324 @ Test
@@ -430,14 +444,15 @@ void isEmptyWhenThereIsNoElements() {
430444
431445 @ Test
432446 @ Order (13 )
433- @ DisplayName ("remove deletes the entry and returns a value" )
447+ @ DisplayName ("remove deletes the entry, decreases table size and returns a value" )
434448 void remove () {
435449 addToTable ("madmax" , 833 );
436-
450+ setSize ( 1 );
437451 var result = hashTable .remove ("madmax" );
438452
439453 assertThat (result ).isEqualTo (833 );
440454 assertFalse (checkKeyValueExists ("madmaxx" , 833 ));
455+ assertEquals (0 , getSize ());
441456 }
442457
443458 @ Test
@@ -451,34 +466,40 @@ void removeWhenKeyDoesNotExists() {
451466
452467 @ Test
453468 @ Order (15 )
454- @ DisplayName ("remove deletes the element when it's in the middle of the list" )
469+ @ DisplayName ("remove deletes the element when it's in the middle of the list and decreases the size of table " )
455470 void removeFromTheMiddleOfTheList () {
456471 addToTable ("AaAa" , 843 );
457472 addToTable ("BBBB" , 434 );
458473 addToTable ("AaBB" , 587 );
459474
475+ var size = 3 ;
476+ setSize (size );
460477 var removedValue = hashTable .remove ("BBBB" );
461478
462479 assertTrue (checkKeyValueExists ("AaAa" , 843 ));
463480 assertFalse (checkKeyExists ("BBBB" ));
464481 assertTrue (checkKeyValueExists ("AaBB" , 587 ));
465482 assertThat (removedValue ).isEqualTo (434 );
466- }
467-
483+ assertEquals (size - 1 , getSize ());
484+ }
485+
468486 @ Test
469487 @ Order (16 )
470- @ DisplayName ("remove deletes the element when it's in the end of the list" )
488+ @ DisplayName ("remove deletes the element when it's in the end of the list and decreases the size of table " )
471489 void removeFromTheEndOfTheList () {
472490 addToTable ("AaAa" , 843 );
473491 addToTable ("BBBB" , 434 );
474492 addToTable ("AaBB" , 587 );
493+ var size = 3 ;
494+ setSize (size );
475495
476496 var removedValue = hashTable .remove ("AaBB" );
477497
478498 assertTrue (checkKeyValueExists ("AaAa" , 843 ));
479499 assertTrue (checkKeyValueExists ("BBBB" , 434 ));
480500 assertFalse (checkKeyExists ("AaBB" ));
481501 assertThat (removedValue ).isEqualTo (587 );
502+ assertEquals (2 , getSize ());
482503 }
483504 }
484505
@@ -585,6 +606,13 @@ private void setSize(int size) {
585606 sizeField .set (hashTable , size );
586607 }
587608
609+ @ SneakyThrows
610+ private int getSize () {
611+ var sizeField = HashTable .class .getDeclaredField ("size" );
612+ sizeField .setAccessible (true );
613+ return sizeField .getInt (hashTable );
614+ }
615+
588616 private String tableToString (Object [] table ) {
589617 StringBuilder result = new StringBuilder ();
590618 var n = table .length ;
0 commit comments