@@ -155,8 +155,6 @@ public class RpcApiServicesTest {
155155
156156 @ BeforeClass
157157 public static void init () throws IOException {
158- System .out .println ("========== [BEFORE_CLASS] Starting init() ==========" );
159- System .err .println ("========== [BEFORE_CLASS] Starting init() ==========" );
160158 Args .setParam (new String [] {"-d" , temporaryFolder .newFolder ().toString ()}, Constant .TEST_CONF );
161159 Assert .assertEquals (5 , getInstance ().getRpcMaxRstStream ());
162160 Assert .assertEquals (10 , getInstance ().getRpcSecondsPerWindow ());
@@ -206,35 +204,20 @@ public static void init() throws IOException {
206204 manager .getAccountStore ().put (ownerCapsule .createDbKey (), ownerCapsule );
207205 manager .getDynamicPropertiesStore ().saveAllowShieldedTransaction (1 );
208206 manager .getDynamicPropertiesStore ().saveAllowShieldedTRC20Transaction (1 );
209- System .out .println ("========== [BEFORE_CLASS] Creating Application... ==========" );
210- System .err .println ("========== [BEFORE_CLASS] Creating Application... ==========" );
211207 appTest = ApplicationFactory .create (context );
212- System .out .println ("========== [BEFORE_CLASS] Starting Application... ==========" );
213- System .err .println ("========== [BEFORE_CLASS] Starting Application... ==========" );
214208 appTest .startup ();
215- System .out .println ("========== [BEFORE_CLASS] Application started ==========" );
216- System .err .println ("========== [BEFORE_CLASS] Application started ==========" );
217209
218- // Initialize stress test channels (increased to 30 for more pressure)
219- System .out .println ("========== [BEFORE_CLASS] Initializing stress test channels... ==========" );
220- System .err .println ("========== [BEFORE_CLASS] Initializing stress test channels... ==========" );
221- int stressChannelCount = 30 ;
210+ // Initialize stress test channels (increased to 100 for maximum pressure)
211+ int stressChannelCount = 100 ;
222212 stressChannels = new ManagedChannel [stressChannelCount ];
223213 stressStubs = new WalletBlockingStub [stressChannelCount ];
224214 for (int i = 0 ; i < stressChannelCount ; i ++) {
225- if (i % 10 == 0 ) {
226- System .out .println ("========== [BEFORE_CLASS] Creating stress channel " + i + "/" + stressChannelCount + " ==========" );
227- System .err .println ("========== [BEFORE_CLASS] Creating stress channel " + i + "/" + stressChannelCount + " ==========" );
228- }
229215 stressChannels [i ] = ManagedChannelBuilder .forTarget (fullNode )
230216 .usePlaintext ()
231217 .intercept (new TimeoutInterceptor (5000 ))
232218 .build ();
233219 stressStubs [i ] = WalletGrpc .newBlockingStub (stressChannels [i ]);
234220 }
235- System .out .println ("========== [BEFORE_CLASS] Initialized " + stressChannelCount + " stress test channels ==========" );
236- System .err .println ("========== [BEFORE_CLASS] Initialized " + stressChannelCount + " stress test channels ==========" );
237- logger .info ("Initialized {} stress test channels" , stressChannelCount );
238221 }
239222
240223 @ AfterClass
@@ -263,14 +246,10 @@ public static void destroy() {
263246
264247 @ Before
265248 public void start () {
266- logger .debug ("========== Starting test: {} ==========" , name .getMethodName ());
267- System .out .println ("========== Starting test: " + name .getMethodName () + " ==========" );
268249 }
269250
270251 @ After
271252 public void end () throws InterruptedException {
272- logger .debug ("========== Ending test: {} ==========" , name .getMethodName ());
273- System .out .println ("========== Ending test: " + name .getMethodName () + " ==========" );
274253 }
275254
276255 @ Test
@@ -428,213 +407,47 @@ public void testGetCanDelegatedMaxSize() {
428407 }
429408
430409 /**
431- * Stress test to reproduce potential gRPC-Java ThreadlessExecutor bug.
432- * This test creates multiple channels and executes concurrent requests to increase
433- * the probability of triggering the callback submission failure issue.
410+ * Continuous stress test that runs until it hangs (to reproduce the bug).
411+ * Maximum stress on gRPC-Java-Netty event handling - no logging overhead.
434412 */
435- @ Test (timeout = 60000 ) // 60 seconds timeout
436- public void testStressMultipleChannels () throws InterruptedException {
437- System .out .println ("========== Starting stress test with multiple channels ==========" );
438- logger .info ("========== Starting stress test with multiple channels ==========" );
439-
440- int threadCount = 50 ; // Increased from 20 to 50
441- int requestsPerThread = 100 ; // Increased from 50 to 100
442- int totalRequests = threadCount * requestsPerThread ;
443-
444- System .out .println ("Thread count: " + threadCount + ", Requests per thread: " + requestsPerThread + ", Total requests: " + totalRequests );
445-
446- ExecutorService executor = Executors .newFixedThreadPool (threadCount );
447- CountDownLatch latch = new CountDownLatch (totalRequests );
448- AtomicInteger successCount = new AtomicInteger (0 );
449- AtomicInteger failureCount = new AtomicInteger (0 );
450- List <Exception > exceptions = new ArrayList <>();
451-
413+ @ Test (timeout = 300000 ) // 5 minutes timeout - will hang if bug occurs
414+ public void testContinuousStressUntilHang () throws InterruptedException {
452415 CanDelegatedMaxSizeRequestMessage message = CanDelegatedMaxSizeRequestMessage .newBuilder ()
453416 .setType (0 ).setOwnerAddress (ownerAddress ).build ();
454-
455- // Submit requests using all available channels
456- for (int i = 0 ; i < totalRequests ; i ++) {
417+
418+ // Maximum stress: 200 threads × 500 requests = 100,000 requests per iteration
419+ int threadCount = 200 ;
420+ int requestsPerIteration = 500 ;
421+ int iterationTotalRequests = threadCount * requestsPerIteration ;
422+
423+ ExecutorService executor = Executors .newFixedThreadPool (threadCount );
424+ CountDownLatch latch = new CountDownLatch (iterationTotalRequests );
425+
426+ for (int i = 0 ; i < iterationTotalRequests ; i ++) {
457427 final int requestId = i ;
458428 executor .submit (() -> {
459429 try {
460- // Distribute requests across all channels
430+ // Distribute requests across all channels to maximize event loop pressure
461431 if (requestId % 3 == 0 ) {
462- // Use blockingStubFull
463432 assertNotNull (blockingStubFull .getCanDelegatedMaxSize (message ));
464433 } else if (requestId % 3 == 1 && stressStubs != null && stressStubs .length > 0 ) {
465- // Use stress stubs
466434 assertNotNull (stressStubs [requestId % stressStubs .length ].getCanDelegatedMaxSize (message ));
467435 } else {
468- // Use blockingStubSolidity (WalletSolidityBlockingStub)
469436 assertNotNull (blockingStubSolidity .getCanDelegatedMaxSize (message ));
470437 }
471-
472- successCount .incrementAndGet ();
473- } catch (Exception e ) {
474- failureCount .incrementAndGet ();
475- synchronized (exceptions ) {
476- exceptions .add (e );
477- }
478- logger .error ("Request {} failed" , requestId , e );
479438 } finally {
480439 latch .countDown ();
481440 }
482441 });
483442 }
484-
485- // Wait for all requests to complete with timeout (increased to 55 seconds)
486- boolean completed = latch .await (55 , TimeUnit .SECONDS );
487-
443+
444+ // Wait for completion - if this hangs, the bug is reproduced!
445+ latch .await (120 , TimeUnit .SECONDS );
446+
488447 executor .shutdown ();
489448 if (!executor .awaitTermination (5 , TimeUnit .SECONDS )) {
490449 executor .shutdownNow ();
491450 }
492-
493- System .out .println ("========== Stress test completed ==========" );
494- System .out .println ("Total requests: " + totalRequests );
495- System .out .println ("Success: " + successCount .get () + ", Failure: " + failureCount .get ());
496- System .out .println ("Completed: " + completed );
497-
498- logger .info ("========== Stress test completed ==========" );
499- logger .info ("Total requests: {}" , totalRequests );
500- logger .info ("Success: {}, Failure: {}" , successCount .get (), failureCount .get ());
501- logger .info ("Completed: {}" , completed );
502-
503- if (!exceptions .isEmpty ()) {
504- System .out .println ("First exception: " + exceptions .get (0 ).getMessage ());
505- logger .error ("First exception: {}" , exceptions .get (0 ).getMessage (), exceptions .get (0 ));
506- }
507-
508- // Assert that all requests completed
509- Assert .assertTrue ("Not all requests completed in time. Success: " + successCount .get ()
510- + ", Failure: " + failureCount .get () + ", Completed: " + completed ,
511- completed );
512-
513- // Log if there were failures (might indicate the bug)
514- if (failureCount .get () > 0 ) {
515- System .out .println ("WARNING: Stress test detected " + failureCount .get () + " failures, which might indicate the ThreadlessExecutor bug" );
516- logger .warn ("Stress test detected {} failures, which might indicate the ThreadlessExecutor bug" ,
517- failureCount .get ());
518- }
519- }
520-
521- /**
522- * Continuous stress test that runs until it hangs (to reproduce the bug).
523- * This test will keep running until it times out or hangs, increasing the probability
524- * of reproducing the ThreadlessExecutor callback submission failure.
525- */
526- @ Test (timeout = 300000 ) // 5 minutes timeout - will hang if bug occurs
527- public void testContinuousStressUntilHang () throws InterruptedException {
528- System .out .println ("========== [TEST] Starting CONTINUOUS stress test (will run until hang) ==========" );
529- System .err .println ("========== [TEST] Starting CONTINUOUS stress test (will run until hang) ==========" );
530- logger .info ("========== Starting CONTINUOUS stress test (will run until hang) ==========" );
531-
532- CanDelegatedMaxSizeRequestMessage message = CanDelegatedMaxSizeRequestMessage .newBuilder ()
533- .setType (0 ).setOwnerAddress (ownerAddress ).build ();
534-
535- int iteration = 0 ;
536- int totalRequests = 0 ;
537- int totalSuccess = 0 ;
538- int totalFailures = 0 ;
539- long startTime = System .currentTimeMillis ();
540-
541- // Run continuously until timeout or hang
542- while (true ) {
543- iteration ++;
544- final int currentIteration = iteration ; // Make final for lambda
545- System .out .println ("\n ========== Iteration " + currentIteration + " ==========" );
546- System .err .println ("\n ========== Iteration " + currentIteration + " ==========" );
547- System .out .flush ();
548- System .err .flush ();
549- logger .info ("========== Iteration {} ==========" , currentIteration );
550-
551- // Each iteration: 50 threads × 100 requests = 5000 requests
552- int threadCount = 50 ;
553- int requestsPerIteration = 100 ;
554- int iterationTotalRequests = threadCount * requestsPerIteration ;
555-
556- ExecutorService executor = Executors .newFixedThreadPool (threadCount );
557- CountDownLatch latch = new CountDownLatch (iterationTotalRequests );
558- AtomicInteger successCount = new AtomicInteger (0 );
559- AtomicInteger failureCount = new AtomicInteger (0 );
560-
561- long iterationStartTime = System .currentTimeMillis ();
562-
563- for (int i = 0 ; i < iterationTotalRequests ; i ++) {
564- final int requestId = i ;
565- executor .submit (() -> {
566- try {
567- // Distribute requests across all channels
568- if (requestId % 3 == 0 ) {
569- assertNotNull (blockingStubFull .getCanDelegatedMaxSize (message ));
570- } else if (requestId % 3 == 1 && stressStubs != null && stressStubs .length > 0 ) {
571- assertNotNull (stressStubs [requestId % stressStubs .length ].getCanDelegatedMaxSize (message ));
572- } else {
573- assertNotNull (blockingStubSolidity .getCanDelegatedMaxSize (message ));
574- }
575- successCount .incrementAndGet ();
576- } catch (Exception e ) {
577- failureCount .incrementAndGet ();
578- logger .error ("Request {} failed in iteration {}" , requestId , currentIteration , e );
579- } finally {
580- latch .countDown ();
581- }
582- });
583- }
584-
585- System .out .println ("All requests submitted, waiting for completion..." );
586- System .err .println ("All requests submitted, waiting for completion..." );
587- System .out .flush ();
588- System .err .flush ();
589-
590- // Wait for completion with timeout - if this hangs, the bug is reproduced!
591- boolean completed = latch .await (60 , TimeUnit .SECONDS );
592-
593- executor .shutdown ();
594- if (!executor .awaitTermination (5 , TimeUnit .SECONDS )) {
595- executor .shutdownNow ();
596- }
597-
598- long iterationTime = System .currentTimeMillis () - iterationStartTime ;
599- totalRequests += iterationTotalRequests ;
600- totalSuccess += successCount .get ();
601- totalFailures += failureCount .get ();
602-
603- System .out .println ("Iteration " + currentIteration + " completed in " + iterationTime + "ms" );
604- System .err .println ("Iteration " + currentIteration + " completed in " + iterationTime + "ms" );
605- System .out .println (" Requests: " + iterationTotalRequests + ", Success: " + successCount .get () + ", Failure: " + failureCount .get ());
606- System .err .println (" Requests: " + iterationTotalRequests + ", Success: " + successCount .get () + ", Failure: " + failureCount .get ());
607- System .out .println (" Completed: " + completed );
608- System .err .println (" Completed: " + completed );
609- System .out .println ("Total so far - Requests: " + totalRequests + ", Success: " + totalSuccess + ", Failure: " + totalFailures );
610- System .err .println ("Total so far - Requests: " + totalRequests + ", Success: " + totalSuccess + ", Failure: " + totalFailures );
611- System .out .println ("Elapsed time: " + (System .currentTimeMillis () - startTime ) + "ms" );
612- System .err .println ("Elapsed time: " + (System .currentTimeMillis () - startTime ) + "ms" );
613-
614- logger .info ("Iteration {} completed in {}ms" , currentIteration , iterationTime );
615- logger .info (" Requests: {}, Success: {}, Failure: {}" , iterationTotalRequests , successCount .get (), failureCount .get ());
616- logger .info ("Total so far - Requests: {}, Success: {}, Failure: {}" , totalRequests , totalSuccess , totalFailures );
617-
618- if (!completed ) {
619- System .out .println ("\n !!! WARNING: Iteration " + currentIteration + " did not complete in time - THIS MIGHT BE THE BUG !!!" );
620- System .err .println ("\n !!! WARNING: Iteration " + currentIteration + " did not complete in time - THIS MIGHT BE THE BUG !!!" );
621- logger .error ("!!! WARNING: Iteration {} did not complete in time - THIS MIGHT BE THE BUG !!!" , currentIteration );
622- // Continue anyway to see if it recovers
623- }
624-
625- if (failureCount .get () > 0 ) {
626- System .out .println ("WARNING: Iteration " + currentIteration + " had " + failureCount .get () + " failures" );
627- System .err .println ("WARNING: Iteration " + currentIteration + " had " + failureCount .get () + " failures" );
628- logger .warn ("Iteration {} had {} failures" , currentIteration , failureCount .get ());
629- }
630-
631- // Force flush output
632- System .out .flush ();
633- System .err .flush ();
634-
635- // Small delay between iterations to avoid overwhelming the system
636- Thread .sleep (100 );
637- }
638451 }
639452
640453 @ Test
0 commit comments