44import static org .junit .jupiter .api .Assertions .assertFalse ;
55import static org .junit .jupiter .api .Assertions .assertThrows ;
66import static org .junit .jupiter .api .Assertions .assertTrue ;
7+ import static org .junit .jupiter .api .Assertions .assertNull ;
78
89import org .junit .jupiter .api .Test ;
10+ import org .junit .jupiter .api .BeforeEach ;
11+ import org .junit .jupiter .api .DisplayName ;
912
1013class NodeStackTest {
1114
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+
1224 @ Test
25+ @ DisplayName ("Test push operation" )
1326 void testPush () {
1427 NodeStack <Integer > stack = new NodeStack <>();
1528 stack .push (10 );
@@ -18,6 +31,7 @@ void testPush() {
1831 }
1932
2033 @ Test
34+ @ DisplayName ("Test pop operation" )
2135 void testPop () {
2236 NodeStack <String > stack = new NodeStack <>();
2337 stack .push ("First" );
@@ -27,12 +41,14 @@ void testPop() {
2741 }
2842
2943 @ Test
44+ @ DisplayName ("Test pop on empty stack throws exception" )
3045 void testPopOnEmptyStack () {
3146 NodeStack <Double > stack = new NodeStack <>();
3247 assertThrows (IllegalStateException .class , stack ::pop , "Popping an empty stack should throw IllegalStateException." );
3348 }
3449
3550 @ Test
51+ @ DisplayName ("Test peek operation" )
3652 void testPeek () {
3753 NodeStack <Integer > stack = new NodeStack <>();
3854 stack .push (5 );
@@ -43,12 +59,14 @@ void testPeek() {
4359 }
4460
4561 @ Test
62+ @ DisplayName ("Test peek on empty stack throws exception" )
4663 void testPeekOnEmptyStack () {
4764 NodeStack <String > stack = new NodeStack <>();
4865 assertThrows (IllegalStateException .class , stack ::peek , "Peeking an empty stack should throw IllegalStateException." );
4966 }
5067
5168 @ Test
69+ @ DisplayName ("Test isEmpty method" )
5270 void testIsEmpty () {
5371 NodeStack <Character > stack = new NodeStack <>();
5472 assertTrue (stack .isEmpty (), "Newly initialized stack should be empty." );
@@ -59,6 +77,7 @@ void testIsEmpty() {
5977 }
6078
6179 @ Test
80+ @ DisplayName ("Test size method" )
6281 void testSize () {
6382 NodeStack <Integer > stack = new NodeStack <>();
6483 assertEquals (0 , stack .size (), "Size of empty stack should be 0." );
@@ -70,4 +89,164 @@ void testSize() {
7089 stack .pop ();
7190 assertEquals (0 , stack .size (), "Size should be 0 after popping all elements." );
7291 }
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