package org.infinispan.spring.session;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.infinispan.spring.provider.SpringCache;
import org.infinispan.spring.session.util.EventsWaiter;
import org.infinispan.test.AbstractInfinispanTest;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.session.MapSession;
import org.springframework.session.events.SessionCreatedEvent;
import org.springframework.session.events.SessionDeletedEvent;
import org.springframework.session.events.SessionExpiredEvent;
import org.testng.annotations.Test;
public abstract class InfinispanApplicationPublishedBridgeTCK extends AbstractInfinispanTest {
protected SpringCache springCache;
protected AbstractInfinispanSessionRepository sessionRepository;
protected abstract SpringCache createSpringCache();
protected abstract void callEviction();
protected abstract AbstractInfinispanSessionRepository createRepository(SpringCache springCache) throws Exception;
protected void init() throws Exception {
springCache = createSpringCache();
sessionRepository = createRepository(springCache);
}
@Test
public void testEventBridge() throws Exception {
//given
EventsCollector eventsCollector = new EventsCollector();
sessionRepository.setApplicationEventPublisher(eventsCollector);
//when
MapSession sessionToBeDeleted = sessionRepository.createSession();
MapSession sessionToBeExpired = sessionRepository.createSession();
sessionToBeExpired.setMaxInactiveIntervalInSeconds(1);
sessionRepository.save(sessionToBeExpired);
sessionRepository.save(sessionToBeDeleted);
sessionRepository.delete(sessionToBeDeleted.getId());
sleepOneSecond();
callEviction();
//then
assertNull(springCache.get(sessionToBeExpired.getId()));
assertNull(springCache.get(sessionToBeDeleted.getId()));
EventsWaiter.assertNumberOfEvents(() -> eventsCollector.getEvents(), SessionCreatedEvent.class, 2, 2, TimeUnit.SECONDS);
EventsWaiter.assertNumberOfEvents(() -> eventsCollector.getEvents(), SessionDeletedEvent.class, 1, 2, TimeUnit.SECONDS);
EventsWaiter.assertNumberOfEvents(() -> eventsCollector.getEvents(), SessionExpiredEvent.class, 1, 2, TimeUnit.SECONDS);
//FIXME: This doesn't work for remote... why? https://issues.jboss.org/browse/ISPN-7040
// EventsWaiter.assertNumberOfEvents(() -> eventsCollector.getEvents(), SessionDestroyedEvent.class, 2, 10, TimeUnit.SECONDS);
}
private void sleepOneSecond() {
long oneSecondSleep = System.currentTimeMillis() + 1000;
eventually(() -> System.currentTimeMillis() > oneSecondSleep);
}
@Test
public void testUnregistration() throws Exception {
//given
EventsCollector eventsCollector = new EventsCollector();
sessionRepository.setApplicationEventPublisher(eventsCollector);
//when
sessionRepository.destroy(); //simulate closing app context
MapSession sessionToBeExpired = sessionRepository.createSession();
sessionRepository.save(sessionToBeExpired);
//then
assertEquals(eventsCollector.getEvents().count(), 0);
}
static class EventsCollector implements ApplicationEventPublisher {
private List<ApplicationEvent> events = new CopyOnWriteArrayList<>();
@Override
public void publishEvent(ApplicationEvent event) {
events.add(event);
}
@Override
public void publishEvent(Object event) {
publishEvent(new PayloadApplicationEvent<>(this, event));
}
public Stream<ApplicationEvent> getEvents() {
return events.stream();
}
}
}