/**
   * Tests update of session expiration in memcached (like {@link
   * #testExpirationOfSessionsInMemcachedIfBackupWasSkippedSimple()}) but for the scenario where
   * many readonly requests occur: in this case, we cannot just use <em>maxInactiveInterval -
   * secondsSinceLastBackup</em> (in {@link MemcachedSessionService#updateExpirationInMemcached}) to
   * determine if an expiration update is required, but we must use the last expiration time sent to
   * memcached.
   *
   * @throws Exception if something goes wrong with the http communication with tomcat
   */
  @Test(enabled = true, dataProviderClass = TestUtils.class, dataProvider = STICKYNESS_PROVIDER)
  public void testExpirationOfSessionsInMemcachedIfBackupWasSkippedManyReadonlyRequests(
      final SessionAffinityMode stickyness) throws Exception {

    final SessionManager manager = _tomcat1.getManager();
    setStickyness(stickyness);

    // set to 1 sec above (in setup), default is 10 seconds
    final int delay = manager.getContainer().getBackgroundProcessorDelay();
    manager.setMaxInactiveInterval(delay * 4);

    final String sessionId1 = makeRequest(_httpClient, _portTomcat1, null);
    assertNotNull(sessionId1, "No session created.");
    assertWaitingWithProxy(Predicates.<MemcachedClientIF>notNull(), 200l, _memcached)
        .get(sessionId1);

    /* after 3 seconds make another request without changing the session, so that
     * it's not sent to memcached
     */
    Thread.sleep(TimeUnit.SECONDS.toMillis(delay * 3));
    assertEquals(
        makeRequest(_httpClient, _portTomcat1, sessionId1),
        sessionId1,
        "SessionId should be the same");
    assertNotNull(_memcached.get(sessionId1), "Session should still exist in memcached.");

    /* after another 3 seconds make another request without changing the session
     */
    Thread.sleep(TimeUnit.SECONDS.toMillis(delay * 3));
    assertEquals(
        makeRequest(_httpClient, _portTomcat1, sessionId1),
        sessionId1,
        "SessionId should be the same");
    assertNotNull(_memcached.get(sessionId1), "Session should still exist in memcached.");

    /* after another nearly 4 seconds (maxInactiveInterval) check that the session is still alive in memcached,
     * this would have been expired without an updated expiration
     */
    Thread.sleep(TimeUnit.SECONDS.toMillis(manager.getMaxInactiveInterval()) - 500);
    assertNotNull(_memcached.get(sessionId1), "Session should still exist in memcached.");

    /* after another second in sticky mode (more than 4 seconds since the last request), or an two times the
     * maxInactiveInterval in non-sticky mode (we must keep sessions in memcached with double expirationtime)
     * the session must be expired in memcached
     */
    Thread.sleep(TimeUnit.SECONDS.toMillis(delay) + 500);
    assertNotSame(
        makeRequest(_httpClient, _portTomcat1, sessionId1),
        sessionId1,
        "The sessionId should have changed due to expired sessin");
  }
  /**
   * Test for issue #60 (Add possibility to disable msm at runtime): start msm disabled and
   * afterwards enable
   */
  @Test(enabled = true)
  public void testStartMsmDisabled() throws Exception {

    // shutdown our server and our client
    _memcached.shutdown();
    _daemon.stop();

    // start a new tomcat with msm initially disabled
    _tomcat1.stop();
    Thread.sleep(500);
    final String memcachedNodes = _memcachedNodeId + ":localhost:" + _memcachedPort;
    _tomcat1 =
        getTestUtils()
            .tomcatBuilder()
            .port(_portTomcat1)
            .memcachedNodes(memcachedNodes)
            .sticky(true)
            .enabled(false)
            .jvmRoute("app1")
            .buildAndStart();

    LOG.info("Waiting, check logs to see if the client causes any 'Connection refused' logging...");
    Thread.sleep(1000);

    // some basic tests for session functionality
    checkSessionFunctionalityWithMsmDisabled();

    // start memcached, client and reenable msm
    _daemon.start();
    _memcached =
        createMemcachedClient(memcachedNodes, new InetSocketAddress("localhost", _memcachedPort));
    _tomcat1.getManager().setEnabled(true);
    // Wait a little bit, so that msm's memcached client can connect and is ready when test starts
    Thread.sleep(100);

    // memcached based stuff should work again
    final String sessionId1 = makeRequest(_httpClient, _portTomcat1, null);
    assertNotNull(sessionId1, "No session created.");
    assertNotNull(
        new SessionIdFormat().extractMemcachedId(sessionId1),
        "memcached node id missing with msm switched to enabled");
    Thread.sleep(50);
    assertNotNull(_memcached.get(sessionId1), "Session not available in memcached.");

    waitForSessionExpiration(true);

    assertNull(_memcached.get(sessionId1), "Expired session still existing in memcached");
  }
 @Test
 public void getString() throws TimeoutException, CacheException {
   EasyMock.expect(client.get("key1")).andReturn("test-value");
   EasyMock.replay(client);
   assertEquals("test-value", clientWrapper.get("key1"));
   EasyMock.verify(client);
 }
 @Test
 @SuppressWarnings("unchecked")
 public void getStringMemcacheTranscoderOfT() throws CacheException, TimeoutException {
   CacheTranscoder transcoder = EasyMock.createMock(CacheTranscoder.class);
   EasyMock.expect(client.get(EasyMock.eq("key1"), EasyMock.anyObject(Transcoder.class)))
       .andReturn("test-value");
   EasyMock.replay(client);
   assertEquals("test-value", clientWrapper.get("key1", transcoder));
   EasyMock.verify(client);
 }
  @Test(enabled = true, dataProviderClass = TestUtils.class, dataProvider = STICKYNESS_PROVIDER)
  public void testSessionAvailableInMemcached(final SessionAffinityMode sessionAffinity)
      throws IOException, InterruptedException, HttpException {

    setStickyness(sessionAffinity);

    final String sessionId1 = makeRequest(_httpClient, _portTomcat1, null);
    assertNotNull(sessionId1, "No session created.");
    Thread.sleep(50);
    assertNotNull(_memcached.get(sessionId1), "Session not available in memcached.");
  }
  @Test(enabled = true, dataProviderClass = TestUtils.class, dataProvider = STICKYNESS_PROVIDER)
  public void testInvalidatedSessionRemovedFromMemcached(
      @Nonnull final SessionAffinityMode sessionAffinity)
      throws IOException, InterruptedException, HttpException {

    setStickyness(sessionAffinity);

    final String sessionId1 = makeRequest(_httpClient, _portTomcat1, null);
    assertNotNull(sessionId1, "No session created.");

    final Response response = get(_httpClient, _portTomcat1, PATH_INVALIDATE, sessionId1);
    assertNull(response.getResponseSessionId());
    assertEquals(_daemon.getCache().getGetMisses(), 1); // 1 is ok

    assertNull(_memcached.get(sessionId1), "Invalidated session still existing in memcached");
    if (!sessionAffinity.isSticky()) {
      assertNull(
          _memcached.get(createValidityInfoKeyName(sessionId1)),
          "ValidityInfo for invalidated session still exists in memcached.");
    }
  }
  /**
   * Tests, that for a session that was not sent to memcached (because it's attributes were not
   * modified), the expiration is updated so that they don't expire in memcached before they expire
   * in tomcat.
   *
   * @throws Exception if something goes wrong with the http communication with tomcat
   */
  @Test(enabled = true, dataProviderClass = TestUtils.class, dataProvider = STICKYNESS_PROVIDER)
  public void testExpirationOfSessionsInMemcachedIfBackupWasSkippedSimple(
      final SessionAffinityMode stickyness) throws Exception {

    final SessionManager manager = _tomcat1.getManager();
    setStickyness(stickyness);

    // set to 1 sec above (in setup), default is 10 seconds
    final int delay = manager.getContainer().getBackgroundProcessorDelay();
    manager.setMaxInactiveInterval(delay * 4);

    final String sessionId1 = makeRequest(_httpClient, _portTomcat1, null);
    assertNotNull(sessionId1, "No session created.");
    assertNotNull(_memcached.get(sessionId1), "Session not available in memcached.");

    /* after 2 seconds make another request without changing the session, so that
     * it's not sent to memcached
     */
    Thread.sleep(TimeUnit.SECONDS.toMillis(delay * 2));
    assertEquals(
        makeRequest(_httpClient, _portTomcat1, sessionId1),
        sessionId1,
        "SessionId should be the same");

    /* after another 3 seconds check that the session is still alive in memcached,
     * this would have been expired without an updated expiration
     */
    Thread.sleep(TimeUnit.SECONDS.toMillis(delay * 3));
    assertNotNull(_memcached.get(sessionId1), "Session should still exist in memcached.");

    /* after another >1 second (4 seconds since the last request)
     * the session must be expired in memcached
     */
    Thread.sleep(
        TimeUnit.SECONDS.toMillis(delay) + 500); // +1000 just to be sure that we're >4 secs
    assertNotSame(
        makeRequest(_httpClient, _portTomcat1, sessionId1),
        sessionId1,
        "The sessionId should have changed due to expired sessin");
  }
  @Test(enabled = true, dataProviderClass = TestUtils.class, dataProvider = STICKYNESS_PROVIDER)
  public void testExpiredSessionRemovedFromMemcached(
      @Nonnull final SessionAffinityMode sessionAffinity)
      throws IOException, InterruptedException, HttpException {

    setStickyness(sessionAffinity);

    final String sessionId1 = makeRequest(_httpClient, _portTomcat1, null);
    assertNotNull(sessionId1, "No session created.");

    waitForSessionExpiration(sessionAffinity.isSticky());

    assertNull(_memcached.get(sessionId1), "Expired session still existing in memcached");
  }
  @Test(enabled = true, dataProviderClass = TestUtils.class, dataProvider = STICKYNESS_PROVIDER)
  public void testSessionAvailableInMemcachedWithCookiesDisabled(
      final SessionAffinityMode sessionAffinity) throws Exception {
    _tomcat1.stop();
    _tomcat1 =
        tcBuilder()
            .sticky(sessionAffinity.isSticky())
            .cookies(false)
            .jvmRoute("app1")
            .buildAndStart();

    final Response response = get(_httpClient, _portTomcat1, null);
    final String sessionId = response.get(TestServlet.ID);
    assertNotNull(sessionId, "No session created.");
    Thread.sleep(50);
    assertNotNull(_memcached.get(sessionId), "Session not available in memcached.");
  }
 @Override
 public Object get(final String key) {
   return _memcached.get(key);
 }