@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2014-2019 the original author or authors.
|
||||
*
|
||||
* Licensed 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
|
||||
*
|
||||
* https://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.springframework.session.data.redis;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
|
||||
import org.springframework.session.data.redis.SimpleRedisOperationsSessionRepository.RedisSession;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link SimpleRedisOperationsSessionRepository}.
|
||||
*
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration
|
||||
@WebAppConfiguration
|
||||
class SimpleRedisOperationsSessionRepositoryITests extends AbstractRedisITests {
|
||||
|
||||
@Autowired
|
||||
private SimpleRedisOperationsSessionRepository sessionRepository;
|
||||
|
||||
@Test
|
||||
void save_NewSession_ShouldSaveSession() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
assertThat(session.getMaxInactiveInterval()).isEqualTo(
|
||||
Duration.ofSeconds(MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS));
|
||||
assertThat(session.getAttributeNames())
|
||||
.isEqualTo(Collections.singleton("attribute1"));
|
||||
assertThat(session.<String>getAttribute("attribute1")).isEqualTo("value1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_LastAccessedTimeInPast_ShouldExpireSession() {
|
||||
assertThat(createAndSaveSession(Instant.EPOCH)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_DeletedSession_ShouldThrowException() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
this.sessionRepository.deleteById(session.getId());
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.sessionRepository.save(session))
|
||||
.withMessage("Session was invalidated");
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ConcurrentUpdates_ShouldSaveSession() {
|
||||
RedisSession copy1 = createAndSaveSession(Instant.now());
|
||||
String sessionId = copy1.getId();
|
||||
RedisSession copy2 = this.sessionRepository.findById(sessionId);
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
updateSession(copy1, now.plusSeconds(1L), "attribute2", "value2");
|
||||
this.sessionRepository.save(copy1);
|
||||
updateSession(copy2, now.plusSeconds(2L), "attribute3", "value3");
|
||||
this.sessionRepository.save(copy2);
|
||||
RedisSession session = this.sessionRepository.findById(sessionId);
|
||||
assertThat(session.getLastAccessedTime()).isEqualTo(now.plusSeconds(2L));
|
||||
assertThat(session.getAttributeNames()).hasSize(3);
|
||||
assertThat(session.<String>getAttribute("attribute1")).isEqualTo("value1");
|
||||
assertThat(session.<String>getAttribute("attribute2")).isEqualTo("value2");
|
||||
assertThat(session.<String>getAttribute("attribute3")).isEqualTo("value3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ChangeSessionIdAndUpdateAttribute_ShouldChangeSessionId() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
String originalSessionId = session.getId();
|
||||
updateSession(session, Instant.now(), "attribute1", "value2");
|
||||
String newSessionId = session.changeSessionId();
|
||||
this.sessionRepository.save(session);
|
||||
RedisSession loaded = this.sessionRepository.findById(newSessionId);
|
||||
assertThat(loaded).isNotNull();
|
||||
assertThat(loaded.getAttributeNames()).hasSize(1);
|
||||
assertThat(loaded.<String>getAttribute("attribute1")).isEqualTo("value2");
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_OnlyChangeSessionId_ShouldChangeSessionId() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
String originalSessionId = session.getId();
|
||||
String newSessionId = session.changeSessionId();
|
||||
this.sessionRepository.save(session);
|
||||
assertThat(this.sessionRepository.findById(newSessionId)).isNotNull();
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ChangeSessionIdTwice_ShouldChangeSessionId() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
String originalSessionId = session.getId();
|
||||
updateSession(session, Instant.now(), "attribute1", "value2");
|
||||
String newSessionId1 = session.changeSessionId();
|
||||
updateSession(session, Instant.now(), "attribute1", "value3");
|
||||
String newSessionId2 = session.changeSessionId();
|
||||
this.sessionRepository.save(session);
|
||||
assertThat(this.sessionRepository.findById(newSessionId1)).isNull();
|
||||
assertThat(this.sessionRepository.findById(newSessionId2)).isNotNull();
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ChangeSessionIdOnNewSession_ShouldChangeSessionId() {
|
||||
RedisSession session = this.sessionRepository.createSession();
|
||||
String originalSessionId = session.getId();
|
||||
updateSession(session, Instant.now(), "attribute1", "value1");
|
||||
String newSessionId = session.changeSessionId();
|
||||
this.sessionRepository.save(session);
|
||||
assertThat(this.sessionRepository.findById(newSessionId)).isNotNull();
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ChangeSessionIdSaveTwice_ShouldChangeSessionId() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
String originalSessionId;
|
||||
originalSessionId = session.getId();
|
||||
updateSession(session, Instant.now(), "attribute1", "value1");
|
||||
String newSessionId = session.changeSessionId();
|
||||
this.sessionRepository.save(session);
|
||||
this.sessionRepository.save(session);
|
||||
assertThat(this.sessionRepository.findById(newSessionId)).isNotNull();
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ChangeSessionIdOnDeletedSession_ShouldThrowException() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
String originalSessionId = session.getId();
|
||||
this.sessionRepository.deleteById(originalSessionId);
|
||||
updateSession(session, Instant.now(), "attribute1", "value1");
|
||||
String newSessionId = session.changeSessionId();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.sessionRepository.save(session))
|
||||
.withMessage("Session was invalidated");
|
||||
assertThat(this.sessionRepository.findById(newSessionId)).isNull();
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void save_ChangeSessionIdConcurrent_ShouldThrowException() {
|
||||
RedisSession copy1 = createAndSaveSession(Instant.now());
|
||||
String originalSessionId = copy1.getId();
|
||||
RedisSession copy2 = this.sessionRepository.findById(originalSessionId);
|
||||
Instant now = Instant.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
updateSession(copy1, now.plusSeconds(1L), "attribute2", "value2");
|
||||
String newSessionId1 = copy1.changeSessionId();
|
||||
this.sessionRepository.save(copy1);
|
||||
updateSession(copy2, now.plusSeconds(2L), "attribute3", "value3");
|
||||
String newSessionId2 = copy2.changeSessionId();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.sessionRepository.save(copy2))
|
||||
.withMessage("Session was invalidated");
|
||||
assertThat(this.sessionRepository.findById(newSessionId1)).isNotNull();
|
||||
assertThat(this.sessionRepository.findById(newSessionId2)).isNull();
|
||||
assertThat(this.sessionRepository.findById(originalSessionId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteById_ValidSession_ShouldDeleteSession() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
this.sessionRepository.deleteById(session.getId());
|
||||
assertThat(this.sessionRepository.findById(session.getId())).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteById_DeletedSession_ShouldDoNothing() {
|
||||
RedisSession session = createAndSaveSession(Instant.now());
|
||||
this.sessionRepository.deleteById(session.getId());
|
||||
this.sessionRepository.deleteById(session.getId());
|
||||
assertThat(this.sessionRepository.findById(session.getId())).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteById_NonexistentSession_ShouldDoNothing() {
|
||||
String sessionId = UUID.randomUUID().toString();
|
||||
this.sessionRepository.deleteById(sessionId);
|
||||
assertThat(this.sessionRepository.findById(sessionId)).isNull();
|
||||
}
|
||||
|
||||
private RedisSession createAndSaveSession(Instant lastAccessedTime) {
|
||||
RedisSession session = this.sessionRepository.createSession();
|
||||
session.setLastAccessedTime(lastAccessedTime);
|
||||
session.setAttribute("attribute1", "value1");
|
||||
this.sessionRepository.save(session);
|
||||
return this.sessionRepository.findById(session.getId());
|
||||
}
|
||||
|
||||
private static void updateSession(RedisSession session, Instant lastAccessedTime,
|
||||
String attributeName, Object attributeValue) {
|
||||
session.setLastAccessedTime(lastAccessedTime);
|
||||
session.setAttribute(attributeName, attributeValue);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableSpringHttpSession
|
||||
static class Config extends BaseConfig {
|
||||
|
||||
@Bean
|
||||
public SimpleRedisOperationsSessionRepository sessionRepository(
|
||||
RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return new SimpleRedisOperationsSessionRepository(redisTemplate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user