/**
  * Verifies that getting a value which is expired will return <code>null</code>.
  *
  * @throws Exception
  */
 @Test
 public void getExpiredValue() throws Exception {
   Time start = Time.now();
   Duration timeout = Duration.milliseconds(50);
   StoredResponsesMap map = new StoredResponsesMap(1000, timeout);
   assertEquals(0, map.size());
   map.put("1", new BufferedWebResponse(null));
   assertEquals(1, map.size());
   TimeUnit.MILLISECONDS.sleep(
       timeout.getMilliseconds() * 2); // sleep for twice longer than the timeout
   assertTrue("The timeout has passed.", Time.now().subtract(start).compareTo(timeout) == 1);
   Object value = map.get("1");
   assertNull(value);
 }
  /**
   * https://issues.apache.org/jira/browse/WICKET-5316
   *
   * @throws Exception
   */
  @Test
  public void failToReleaseUnderLoad() throws Exception {
    final Duration duration = Duration.seconds(20); /* seconds */
    final ConcurrentLinkedQueue<Exception> errors = new ConcurrentLinkedQueue<Exception>();
    final long endTime = System.currentTimeMillis() + duration.getMilliseconds();

    // set the synchronizer timeout one second longer than the test runs to prevent
    // starvation to become an issue
    final PageAccessSynchronizer sync =
        new PageAccessSynchronizer(duration.add(Duration.ONE_SECOND));

    final CountDownLatch latch = new CountDownLatch(100);
    for (int count = 0; count < 100; count++) {
      new Thread() {
        @Override
        public void run() {
          try {
            while (System.currentTimeMillis() < endTime) {
              try {
                logger.debug(Thread.currentThread().getName() + " locking");
                sync.lockPage(0);
                Thread.sleep(1);
                logger.debug(Thread.currentThread().getName() + " locked");
                sync.unlockAllPages();
                logger.debug(Thread.currentThread().getName() + " unlocked");
                Thread.sleep(5);
              } catch (InterruptedException e) {
                throw new RuntimeException(e);
              }
            }
          } catch (Exception e) {
            logger.error(e.getMessage(), e);
            errors.add(e);
          } finally {
            latch.countDown();
          }
        }
      }.start();
    }
    latch.await();
    if (!errors.isEmpty()) {
      logger.error("Number of lock errors that occurred: {}", errors.size());
      throw errors.remove();
    }
  }