WICKET-6169 NullPointerException accessing AbstractRequestLogger.getLiveSessions
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/0a6a96bc Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/0a6a96bc Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/0a6a96bc Branch: refs/heads/WICKET-6183 Commit: 0a6a96bcbf42b7d4a31065c23fa36260b454f371 Parents: be7cd7c Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Sat May 21 13:09:17 2016 +0200 Committer: Andrea Del Bene <[email protected]> Committed: Fri May 27 13:12:16 2016 +0200 ---------------------------------------------------------------------- .../protocol/http/AbstractRequestLogger.java | 3 +- .../http/RequestLoggerLiveSessionsTest.java | 123 +++++++++++++++++++ 2 files changed, 124 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/0a6a96bc/wicket-core/src/main/java/org/apache/wicket/protocol/http/AbstractRequestLogger.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/AbstractRequestLogger.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/AbstractRequestLogger.java index 0c5d7d0..8cb8fcd 100644 --- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/AbstractRequestLogger.java +++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/AbstractRequestLogger.java @@ -134,8 +134,7 @@ public abstract class AbstractRequestLogger implements IRequestLogger @Override public SessionData[] getLiveSessions() { - final SessionData[] sessions = liveSessions.values().toArray( - new SessionData[liveSessions.values().size()]); + final SessionData[] sessions = liveSessions.values().toArray(new SessionData[0]); Arrays.sort(sessions); return sessions; } http://git-wip-us.apache.org/repos/asf/wicket/blob/0a6a96bc/wicket-core/src/test/java/org/apache/wicket/protocol/http/RequestLoggerLiveSessionsTest.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/protocol/http/RequestLoggerLiveSessionsTest.java b/wicket-core/src/test/java/org/apache/wicket/protocol/http/RequestLoggerLiveSessionsTest.java new file mode 100644 index 0000000..edbc552 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/protocol/http/RequestLoggerLiveSessionsTest.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.protocol.http; + +import org.apache.wicket.util.SlowTests; +import org.junit.Assert; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import java.util.ArrayList; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Test for https://issues.apache.org/jira/browse/WICKET-6169 + */ +@Category(SlowTests.class) +public class RequestLoggerLiveSessionsTest +{ + private final RequestLogger requestLogger = new RequestLogger(); + + private final ArrayList<String> sessionIds = new ArrayList<>(); + + @Test + public void concurrentModification() { + SessionCreateThread sct = new SessionCreateThread(); + SessionDestroyThread sdt = new SessionDestroyThread(); + sct.start(); + sdt.start(); + AtomicBoolean nullPointerExceptionThrown = new AtomicBoolean(false); + + int count = 10000000; + + while (count-- > 0) + { + try { + requestLogger.getLiveSessions(); + } + catch (NullPointerException e) + { + e.printStackTrace(); + nullPointerExceptionThrown.set(true); + break; + } + } + + sct.interrupt(); + sdt.interrupt(); + + if (nullPointerExceptionThrown.get()) { + Assert.fail("The test should not fail with NullPointerException"); + } + } + + private class SessionCreateThread extends Thread + { + private final Random random = new Random(); + + public void run() + { + while (!isInterrupted()) + { + if (sessionIds.size() < 50) + { + String sessionId = UUID.randomUUID().toString(); + synchronized (sessionIds) { + sessionIds.add(sessionId); + } + requestLogger.sessionCreated(sessionId); + } + + try + { + Thread.sleep(random.nextInt(20)); + } + catch (InterruptedException e) { + } + } + } + } + + private class SessionDestroyThread extends Thread + { + private final Random random = new Random(); + + public void run() + { + while (!isInterrupted()) + { + if (sessionIds.size() > 0) + { + String sessionId = sessionIds.get(random.nextInt(sessionIds.size())); + requestLogger.sessionDestroyed(sessionId); + synchronized (sessionIds) { + sessionIds.remove(sessionId); + } + } + + try + { + Thread.sleep(random.nextInt(20)); + } + catch (InterruptedException e) { + } + } + } + } +}
