@@ -49,6 +49,7 @@ public class PropertiesLoginModuleRaceConditionTest {
4949 private static final String USERS_FILE = "users.properties" ;
5050 private static final String USERNAME = "first" ;
5151 private static final String PASSWORD = "secret" ;
52+ private static final int TOTAL_LOGIN_ATTEMPTS = 25000 ;
5253
5354 @ Rule
5455 public final ErrorCollector e = new ErrorCollector ();
@@ -112,7 +113,8 @@ public void before() throws FileNotFoundException, IOException {
112113 options .put ("org.apache.activemq.jaas.properties.group" , GROUPS_FILE );
113114 options .put ("baseDir" , temp .getRoot ().getAbsolutePath ());
114115
115- errors = new ArrayBlockingQueue <Exception >(processorCount ());
116+ // Large enough to hold all potential errors from concurrent attempts
117+ errors = new ArrayBlockingQueue <Exception >(TOTAL_LOGIN_ATTEMPTS );
116118 pool = Executors .newFixedThreadPool (processorCount ());
117119 callback = new JassCredentialCallbackHandler (USERNAME , PASSWORD );
118120 }
@@ -128,24 +130,27 @@ public void after() throws InterruptedException {
128130 public void raceConditionInUsersAndGroupsLoading () throws InterruptedException , FileNotFoundException , IOException {
129131
130132 // Brute force approach to increase the likelihood of the race condition occurring
131- for (int i = 0 ; i < 25000 ; i ++) {
132- final CountDownLatch start = new CountDownLatch (1 );
133- final CountDownLatch finished = new CountDownLatch (processorCount ());
134- prepareLoginThreads (start , finished );
135-
136- // Releases every login thread simultaneously to increase our chances of
137- // encountering the race condition
138- start .countDown ();
139-
140- finished .await ();
141- if (isRaceConditionDetected ()) {
142- e .addError (new AssertionError ("At least one race condition in PropertiesLoginModule "
143- + "has been encountered. Please examine the "
144- + "following stack traces for more details:" ));
145- for (Exception exception : errors ) {
146- e .addError (exception );
147- }
148- return ;
133+ // Submit many concurrent login attempts and let the thread pool handle concurrency
134+ final CountDownLatch start = new CountDownLatch (1 );
135+ final CountDownLatch finished = new CountDownLatch (TOTAL_LOGIN_ATTEMPTS );
136+
137+ // Submit all login tasks to the pool
138+ for (int i = 0 ; i < TOTAL_LOGIN_ATTEMPTS ; i ++) {
139+ pool .submit (new LoginTester (start , finished , errors , options , callback ));
140+ }
141+
142+ // Release all threads simultaneously to maximize concurrent load
143+ start .countDown ();
144+
145+ // Wait for all attempts to complete
146+ finished .await ();
147+
148+ if (isRaceConditionDetected ()) {
149+ e .addError (new AssertionError ("At least one race condition in PropertiesLoginModule "
150+ + "has been encountered. Please examine the "
151+ + "following stack traces for more details:" ));
152+ for (Exception exception : errors ) {
153+ e .addError (exception );
149154 }
150155 }
151156 }
@@ -154,12 +159,6 @@ private boolean isRaceConditionDetected() {
154159 return errors .size () > 0 ;
155160 }
156161
157- private void prepareLoginThreads (final CountDownLatch start , final CountDownLatch finished ) {
158- for (int processor = 1 ; processor <= processorCount () * 2 ; processor ++) {
159- pool .submit (new LoginTester (start , finished , errors , options , callback ));
160- }
161- }
162-
163162 private int processorCount () {
164163 return Runtime .getRuntime ().availableProcessors ();
165164 }
0 commit comments