1
1
package com .thealgorithms .datastructures .stacks ;
2
2
3
3
import static org .junit .jupiter .api .Assertions .assertEquals ;
4
- import static org .junit .jupiter .api .Assertions .assertFalse ;
5
4
import static org .junit .jupiter .api .Assertions .assertThrows ;
6
5
import static org .junit .jupiter .api .Assertions .assertTrue ;
7
6
7
+ import org .junit .jupiter .api .BeforeEach ;
8
+ import org .junit .jupiter .api .DisplayName ;
8
9
import org .junit .jupiter .api .Test ;
9
10
10
11
class NodeStackTest {
11
12
13
+ private NodeStack <Integer > intStack ;
14
+ private NodeStack <String > stringStack ;
15
+
16
+ @ BeforeEach
17
+ void setUp () {
18
+ intStack = new NodeStack <>();
19
+ stringStack = new NodeStack <>();
20
+ }
21
+
12
22
@ Test
23
+ @ DisplayName ("Test push operation" )
13
24
void testPush () {
14
25
NodeStack <Integer > stack = new NodeStack <>();
15
26
stack .push (10 );
@@ -18,6 +29,7 @@ void testPush() {
18
29
}
19
30
20
31
@ Test
32
+ @ DisplayName ("Test pop operation" )
21
33
void testPop () {
22
34
NodeStack <String > stack = new NodeStack <>();
23
35
stack .push ("First" );
@@ -27,12 +39,14 @@ void testPop() {
27
39
}
28
40
29
41
@ Test
42
+ @ DisplayName ("Test pop on empty stack throws exception" )
30
43
void testPopOnEmptyStack () {
31
44
NodeStack <Double > stack = new NodeStack <>();
32
45
assertThrows (IllegalStateException .class , stack ::pop , "Popping an empty stack should throw IllegalStateException." );
33
46
}
34
47
35
48
@ Test
49
+ @ DisplayName ("Test peek operation" )
36
50
void testPeek () {
37
51
NodeStack <Integer > stack = new NodeStack <>();
38
52
stack .push (5 );
@@ -43,22 +57,25 @@ void testPeek() {
43
57
}
44
58
45
59
@ Test
60
+ @ DisplayName ("Test peek on empty stack throws exception" )
46
61
void testPeekOnEmptyStack () {
47
62
NodeStack <String > stack = new NodeStack <>();
48
63
assertThrows (IllegalStateException .class , stack ::peek , "Peeking an empty stack should throw IllegalStateException." );
49
64
}
50
65
51
66
@ Test
67
+ @ DisplayName ("Test isEmpty method" )
52
68
void testIsEmpty () {
53
69
NodeStack <Character > stack = new NodeStack <>();
54
70
assertTrue (stack .isEmpty (), "Newly initialized stack should be empty." );
55
71
stack .push ('A' );
56
- assertFalse (stack .isEmpty (), "Stack should not be empty after a push operation." );
72
+ org . junit . jupiter . api . Assertions . assertFalse (stack .isEmpty (), "Stack should not be empty after a push operation." );
57
73
stack .pop ();
58
74
assertTrue (stack .isEmpty (), "Stack should be empty after popping the only element." );
59
75
}
60
76
61
77
@ Test
78
+ @ DisplayName ("Test size method" )
62
79
void testSize () {
63
80
NodeStack <Integer > stack = new NodeStack <>();
64
81
assertEquals (0 , stack .size (), "Size of empty stack should be 0." );
@@ -70,4 +87,164 @@ void testSize() {
70
87
stack .pop ();
71
88
assertEquals (0 , stack .size (), "Size should be 0 after popping all elements." );
72
89
}
90
+
91
+ @ Test
92
+ @ DisplayName ("Test push and pop with null values" )
93
+ void testPushPopWithNull () {
94
+ stringStack .push (null );
95
+ stringStack .push ("not null" );
96
+ stringStack .push (null );
97
+
98
+ assertEquals (3 , stringStack .size (), "Stack should contain 3 elements including nulls" );
99
+ org .junit .jupiter .api .Assertions .assertNull (stringStack .pop (), "Should pop null value" );
100
+ assertEquals ("not null" , stringStack .pop (), "Should pop 'not null' value" );
101
+ org .junit .jupiter .api .Assertions .assertNull (stringStack .pop (), "Should pop null value" );
102
+ assertTrue (stringStack .isEmpty (), "Stack should be empty after popping all elements" );
103
+ }
104
+
105
+ @ Test
106
+ @ DisplayName ("Test LIFO (Last In First Out) behavior" )
107
+ void testLifoBehavior () {
108
+ int [] values = {1 , 2 , 3 , 4 , 5 };
109
+
110
+ // Push values in order
111
+ for (int value : values ) {
112
+ intStack .push (value );
113
+ }
114
+
115
+ // Pop values should be in reverse order
116
+ for (int i = values .length - 1 ; i >= 0 ; i --) {
117
+ assertEquals (values [i ], intStack .pop (), "Elements should be popped in LIFO order" );
118
+ }
119
+ }
120
+
121
+ @ Test
122
+ @ DisplayName ("Test peek doesn't modify stack" )
123
+ void testPeekDoesNotModifyStack () {
124
+ intStack .push (1 );
125
+ intStack .push (2 );
126
+ intStack .push (3 );
127
+
128
+ int originalSize = intStack .size ();
129
+ int peekedValue = intStack .peek ();
130
+
131
+ assertEquals (3 , peekedValue , "Peek should return top element" );
132
+ assertEquals (originalSize , intStack .size (), "Peek should not change stack size" );
133
+ assertEquals (3 , intStack .peek (), "Multiple peeks should return same value" );
134
+ org .junit .jupiter .api .Assertions .assertFalse (intStack .isEmpty (), "Peek should not make stack empty" );
135
+ }
136
+
137
+ @ Test
138
+ @ DisplayName ("Test mixed push and pop operations" )
139
+ void testMixedOperations () {
140
+ // Test interleaved push/pop operations
141
+ intStack .push (1 );
142
+ assertEquals (1 , intStack .pop ());
143
+ assertTrue (intStack .isEmpty ());
144
+
145
+ intStack .push (2 );
146
+ intStack .push (3 );
147
+ assertEquals (3 , intStack .pop ());
148
+ intStack .push (4 );
149
+ assertEquals (4 , intStack .peek ());
150
+ assertEquals (2 , intStack .size ());
151
+
152
+ assertEquals (4 , intStack .pop ());
153
+ assertEquals (2 , intStack .pop ());
154
+ assertTrue (intStack .isEmpty ());
155
+ }
156
+
157
+ @ Test
158
+ @ DisplayName ("Test stack with duplicate values" )
159
+ void testStackWithDuplicates () {
160
+ intStack .push (1 );
161
+ intStack .push (1 );
162
+ intStack .push (1 );
163
+
164
+ assertEquals (3 , intStack .size (), "Stack should handle duplicate values" );
165
+ assertEquals (1 , intStack .peek (), "Peek should return duplicate value" );
166
+
167
+ assertEquals (1 , intStack .pop (), "Should pop first duplicate" );
168
+ assertEquals (1 , intStack .pop (), "Should pop second duplicate" );
169
+ assertEquals (1 , intStack .pop (), "Should pop third duplicate" );
170
+ assertTrue (intStack .isEmpty (), "Stack should be empty after popping all duplicates" );
171
+ }
172
+
173
+ @ Test
174
+ @ DisplayName ("Test stack with different data types" )
175
+ void testDifferentDataTypes () {
176
+ NodeStack <Character > charStack = new NodeStack <>();
177
+ NodeStack <Boolean > booleanStack = new NodeStack <>();
178
+
179
+ // Test with Character
180
+ charStack .push ('A' );
181
+ charStack .push ('Z' );
182
+ assertEquals ('Z' , charStack .peek (), "Should handle Character values" );
183
+
184
+ // Test with Boolean
185
+ booleanStack .push (Boolean .TRUE );
186
+ booleanStack .push (Boolean .FALSE );
187
+ assertEquals (Boolean .FALSE , booleanStack .peek (), "Should handle Boolean values" );
188
+ }
189
+
190
+ @ Test
191
+ @ DisplayName ("Test stack state consistency after exceptions" )
192
+ void testStateConsistencyAfterExceptions () {
193
+ // Stack should remain consistent after exception-throwing operations
194
+ intStack .push (1 );
195
+ intStack .push (2 );
196
+
197
+ // Try to peek and pop normally first
198
+ assertEquals (2 , intStack .peek ());
199
+ assertEquals (2 , intStack .pop ());
200
+ assertEquals (1 , intStack .size ());
201
+
202
+ // Pop remaining element
203
+ assertEquals (1 , intStack .pop ());
204
+ assertTrue (intStack .isEmpty ());
205
+
206
+ // Now stack is empty, operations should throw exceptions
207
+ assertThrows (IllegalStateException .class , intStack ::peek );
208
+ assertThrows (IllegalStateException .class , intStack ::pop );
209
+
210
+ // Stack should still be in valid empty state
211
+ assertTrue (intStack .isEmpty ());
212
+ assertEquals (0 , intStack .size ());
213
+
214
+ // Should be able to push after exceptions
215
+ intStack .push (3 );
216
+ org .junit .jupiter .api .Assertions .assertFalse (intStack .isEmpty ());
217
+ assertEquals (1 , intStack .size ());
218
+ assertEquals (3 , intStack .peek ());
219
+ }
220
+
221
+ @ Test
222
+ @ DisplayName ("Test single element stack operations" )
223
+ void testSingleElementStack () {
224
+ intStack .push (2 );
225
+
226
+ org .junit .jupiter .api .Assertions .assertFalse (intStack .isEmpty (), "Stack with one element should not be empty" );
227
+ assertEquals (1 , intStack .size (), "Size should be 1" );
228
+ assertEquals (2 , intStack .peek (), "Peek should return the single element" );
229
+ assertEquals (1 , intStack .size (), "Peek should not change size" );
230
+
231
+ assertEquals (2 , intStack .pop (), "Pop should return the single element" );
232
+ assertTrue (intStack .isEmpty (), "Stack should be empty after popping single element" );
233
+ assertEquals (0 , intStack .size (), "Size should be 0 after popping single element" );
234
+ }
235
+
236
+ @ Test
237
+ @ DisplayName ("Test toString method if implemented" )
238
+ void testToString () {
239
+ // This test assumes NodeStack has a toString method
240
+ // If not implemented, this test can be removed or NodeStack can be enhanced
241
+ intStack .push (1 );
242
+ intStack .push (2 );
243
+ intStack .push (3 );
244
+
245
+ String stackString = intStack .toString ();
246
+ // Basic check that toString doesn't throw exception and returns something
247
+ assertTrue (stackString != null , "toString should not return null" );
248
+ assertTrue (stackString .length () > 0 , "toString should return non-empty string" );
249
+ }
73
250
}
0 commit comments