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