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/**
23- * A Reflection-based step by step test for a {@link HashTable} class. PLEASE NOTE that Reflection API should not be used
24- * for testing a production code. We use it for learning purposes only!
25- *
26- * @author Taras Boychuk
27- */
29+ A Reflection-based step by step test for a {@link HashTable} class. PLEASE NOTE that Reflection API should not be used for testing a
30+ production code. We use it for learning purposes only!
31+ @author Taras Boychuk */
2832@ TestClassOrder (OrderAnnotation .class )
2933@ DisplayName ("HashTable Test" )
3034class HashTableTest {
35+
3136 private HashTable <String , Integer > hashTable = new HashTable <>();
3237
3338 @ Nested
@@ -126,6 +131,7 @@ void nodeConstructorAcceptKeyValue() {
126131 @ DisplayName ("2. HashTable fields Test" )
127132 @ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
128133 class HashTableFieldsTest {
134+
129135 @ Test
130136 @ Order (1 )
131137 @ DisplayName ("HastTable has a field 'table' which is an array of nodes" )
@@ -155,6 +161,7 @@ void sizeFieldExists() {
155161 @ DisplayName ("3. HashTable constructors Test" )
156162 @ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
157163 class HashTableConstructorsTest {
164+
158165 @ Test
159166 @ Order (1 )
160167 @ SneakyThrows
@@ -198,6 +205,7 @@ void constructorWithTableCapacityWhenArgumentIsNegative() {
198205 @ DisplayName ("4. Hash Function Test" )
199206 @ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
200207 class HashFunctionTest {
208+
201209 @ Test
202210 @ Order (1 )
203211 @ DisplayName ("calculateIndex returns the same value for the same key" )
@@ -221,8 +229,8 @@ void calculateIndexReturnDifferentValuesWheKeysAreDifferent() {
221229
222230 assertThat (indexSet )
223231 .hasSizeGreaterThan (1 );
224- }
225-
232+ }
233+
226234 @ Test
227235 @ Order (3 )
228236 @ DisplayName ("calculateIndex returns values in array bounds" )
@@ -235,7 +243,7 @@ void calculateIndexReturnIndexInArrayBounds() {
235243 var indexes = keys .stream ()
236244 .map (key -> HashTable .calculateIndex (key , arrayCapacity ))
237245 .toList ();
238-
246+
239247 assertThat (indexes )
240248 .isNotEmpty ()
241249 .allMatch (i -> i >= 0 && i < arrayCapacity );
@@ -262,19 +270,20 @@ class HashTableMethodsTest {
262270 @ Test
263271 @ SneakyThrows
264272 @ Order (1 )
265- @ DisplayName ("put creates new entry and returns null when the table is empty" )
273+ @ DisplayName ("put creates new entry and returns null when the table is empty, should increase the table size " )
266274 void putWhenTableIsEmpty () {
267275 var previousValue = hashTable .put ("madmax" , 833 );
268276
269277 var keyValueExists = checkKeyValueExists ("madmax" , 833 );
270278
271279 assertNull (previousValue );
272280 assertTrue (keyValueExists );
281+ assertEquals (1 , getSize ());
273282 }
274283
275284 @ Test
276285 @ Order (2 )
277- @ DisplayName ("put elements adds entry to to the same bucket when the hash code is the same" )
286+ @ DisplayName ("put elements adds entry to the same bucket and increases table size when the hash code is the same" )
278287 @ SneakyThrows
279288 void putTwoElementsWithTheSameHashCode () {
280289 var table = getInternalTable (hashTable );
@@ -290,11 +299,13 @@ void putTwoElementsWithTheSameHashCode() {
290299 assertTrue (containsKeyValueA );
291300 assertTrue (containsKeyValueB );
292301 assertThat (bucketIndexA ).isEqualTo (bucketIndexB );
302+ assertEquals (2 , getSize ());
293303 }
294304
295305 @ Test
296306 @ Order (3 )
297- @ DisplayName ("put element updates the value and returns the previous one when key is the same" )
307+ @ DisplayName (
308+ "put element updates the value and returns the previous one when key is the same, should not increase table size" )
298309 void putElementWithTheSameKey () {
299310 hashTable .put ("madmax" , 833 );
300311 System .out .println (hashTable );
@@ -305,6 +316,7 @@ void putElementWithTheSameKey() {
305316
306317 assertThat (previousValue ).isEqualTo (833 );
307318 assertTrue (containsNewValueByKey );
319+ assertEquals (1 , getSize ());
308320 }
309321
310322 @ Test
@@ -430,14 +442,15 @@ void isEmptyWhenThereIsNoElements() {
430442
431443 @ Test
432444 @ Order (13 )
433- @ DisplayName ("remove deletes the entry and returns a value" )
445+ @ DisplayName ("remove deletes the entry, decreases table size and returns a value" )
434446 void remove () {
435447 addToTable ("madmax" , 833 );
436-
448+ setSize ( 1 );
437449 var result = hashTable .remove ("madmax" );
438450
439451 assertThat (result ).isEqualTo (833 );
440452 assertFalse (checkKeyValueExists ("madmaxx" , 833 ));
453+ assertEquals (0 , getSize ());
441454 }
442455
443456 @ Test
@@ -451,34 +464,40 @@ void removeWhenKeyDoesNotExists() {
451464
452465 @ Test
453466 @ Order (15 )
454- @ DisplayName ("remove deletes the element when it's in the middle of the list" )
467+ @ DisplayName ("remove deletes the element when it's in the middle of the list and decreases the size of table " )
455468 void removeFromTheMiddleOfTheList () {
456469 addToTable ("AaAa" , 843 );
457470 addToTable ("BBBB" , 434 );
458471 addToTable ("AaBB" , 587 );
459472
473+ var size = 3 ;
474+ setSize (size );
460475 var removedValue = hashTable .remove ("BBBB" );
461476
462477 assertTrue (checkKeyValueExists ("AaAa" , 843 ));
463478 assertFalse (checkKeyExists ("BBBB" ));
464479 assertTrue (checkKeyValueExists ("AaBB" , 587 ));
465480 assertThat (removedValue ).isEqualTo (434 );
466- }
467-
481+ assertEquals (size - 1 , getSize ());
482+ }
483+
468484 @ Test
469485 @ Order (16 )
470- @ DisplayName ("remove deletes the element when it's in the end of the list" )
486+ @ DisplayName ("remove deletes the element when it's in the end of the list and decreases the size of table " )
471487 void removeFromTheEndOfTheList () {
472488 addToTable ("AaAa" , 843 );
473489 addToTable ("BBBB" , 434 );
474490 addToTable ("AaBB" , 587 );
491+ var size = 3 ;
492+ setSize (size );
475493
476494 var removedValue = hashTable .remove ("AaBB" );
477495
478496 assertTrue (checkKeyValueExists ("AaAa" , 843 ));
479497 assertTrue (checkKeyValueExists ("BBBB" , 434 ));
480498 assertFalse (checkKeyExists ("AaBB" ));
481499 assertThat (removedValue ).isEqualTo (587 );
500+ assertEquals (2 , getSize ());
482501 }
483502 }
484503
@@ -585,6 +604,13 @@ private void setSize(int size) {
585604 sizeField .set (hashTable , size );
586605 }
587606
607+ @ SneakyThrows
608+ private int getSize () {
609+ var sizeField = HashTable .class .getDeclaredField ("size" );
610+ sizeField .setAccessible (true );
611+ return sizeField .getInt (hashTable );
612+ }
613+
588614 private String tableToString (Object [] table ) {
589615 StringBuilder result = new StringBuilder ();
590616 var n = table .length ;
0 commit comments