package com.ctrip.framework.apollo.configservice.service;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.ctrip.framework.apollo.biz.config.BizConfig;
import com.ctrip.framework.apollo.biz.repository.AppNamespaceRepository;
import com.ctrip.framework.apollo.common.entity.AppNamespace;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class AppNamespaceServiceWithCacheTest {
private AppNamespaceServiceWithCache appNamespaceServiceWithCache;
@Mock
private AppNamespaceRepository appNamespaceRepository;
@Mock
private BizConfig bizConfig;
private int scanInterval;
private TimeUnit scanIntervalTimeUnit;
private Comparator<AppNamespace> appNamespaceComparator = (o1, o2) -> (int) (o1.getId() -
o2.getId());
@Before
public void setUp() throws Exception {
appNamespaceServiceWithCache = new AppNamespaceServiceWithCache();
ReflectionTestUtils.setField(appNamespaceServiceWithCache, "appNamespaceRepository",
appNamespaceRepository);
ReflectionTestUtils.setField(appNamespaceServiceWithCache, "bizConfig", bizConfig);
scanInterval = 10;
scanIntervalTimeUnit = TimeUnit.MILLISECONDS;
when(bizConfig.appNamespaceCacheRebuildInterval()).thenReturn(scanInterval);
when(bizConfig.appNamespaceCacheRebuildIntervalTimeUnit()).thenReturn(scanIntervalTimeUnit);
when(bizConfig.appNamespaceCacheScanInterval()).thenReturn(scanInterval);
when(bizConfig.appNamespaceCacheScanIntervalTimeUnit()).thenReturn(scanIntervalTimeUnit);
}
@Test
public void testAppNamespace() throws Exception {
String someAppId = "someAppId";
String somePrivateNamespace = "somePrivateNamespace";
long somePrivateNamespaceId = 1;
String yetAnotherPrivateNamespace = "anotherPrivateNamespace";
long yetAnotherPrivateNamespaceId = 4;
String anotherPublicNamespace = "anotherPublicNamespace";
long anotherPublicNamespaceId = 5;
String somePublicAppId = "somePublicAppId";
String somePublicNamespace = "somePublicNamespace";
long somePublicNamespaceId = 2;
String anotherPrivateNamespace = "anotherPrivateNamespace";
long anotherPrivateNamespaceId = 3;
int sleepInterval = scanInterval * 10;
AppNamespace somePrivateAppNamespace = assembleAppNamespace(somePrivateNamespaceId,
someAppId, somePrivateNamespace, false);
AppNamespace somePublicAppNamespace = assembleAppNamespace(somePublicNamespaceId,
somePublicAppId, somePublicNamespace, true);
AppNamespace anotherPrivateAppNamespace = assembleAppNamespace(anotherPrivateNamespaceId,
somePublicAppId, anotherPrivateNamespace, false);
AppNamespace yetAnotherPrivateAppNamespace = assembleAppNamespace
(yetAnotherPrivateNamespaceId, someAppId, yetAnotherPrivateNamespace, false);
AppNamespace anotherPublicAppNamespace = assembleAppNamespace(anotherPublicNamespaceId,
someAppId, anotherPublicNamespace, true);
Set<String> someAppIdNamespaces = Sets.newHashSet
(somePrivateNamespace, yetAnotherPrivateNamespace, anotherPublicNamespace);
Set<String> somePublicAppIdNamespaces = Sets.newHashSet(somePublicNamespace,
anotherPrivateNamespace);
Set<String> publicNamespaces = Sets.newHashSet(somePublicNamespace, anotherPublicNamespace);
List<Long> appNamespaceIds = Lists.newArrayList(somePrivateNamespaceId,
somePublicNamespaceId, anotherPrivateNamespaceId, yetAnotherPrivateNamespaceId,
anotherPublicNamespaceId);
List<AppNamespace> allAppNamespaces = Lists.newArrayList(somePrivateAppNamespace,
somePublicAppNamespace, anotherPrivateAppNamespace, yetAnotherPrivateAppNamespace,
anotherPublicAppNamespace);
// Test init
appNamespaceServiceWithCache.afterPropertiesSet();
// Should have no record now
assertTrue(appNamespaceServiceWithCache.findByAppIdAndNamespaces(someAppId, someAppIdNamespaces)
.isEmpty());
assertTrue(appNamespaceServiceWithCache.findByAppIdAndNamespaces(somePublicAppId,
somePublicAppIdNamespaces).isEmpty());
assertTrue(appNamespaceServiceWithCache.findPublicNamespacesByNames(publicNamespaces).isEmpty
());
// Add 1 private namespace and 1 public namespace
when(appNamespaceRepository.findFirst500ByIdGreaterThanOrderByIdAsc(0)).thenReturn(Lists
.newArrayList(somePrivateAppNamespace, somePublicAppNamespace));
when(appNamespaceRepository.findAll(Lists.newArrayList(somePrivateNamespaceId,
somePublicNamespaceId))).thenReturn(Lists.newArrayList(somePrivateAppNamespace,
somePublicAppNamespace));
scanIntervalTimeUnit.sleep(sleepInterval);
check(Lists.newArrayList(somePrivateAppNamespace), appNamespaceServiceWithCache
.findByAppIdAndNamespaces(someAppId, someAppIdNamespaces));
check(Lists.newArrayList(somePublicAppNamespace), appNamespaceServiceWithCache
.findByAppIdAndNamespaces(somePublicAppId, somePublicAppIdNamespaces));
check(Lists.newArrayList(somePublicAppNamespace), appNamespaceServiceWithCache
.findPublicNamespacesByNames(publicNamespaces));
// Add 2 private namespaces and 1 public namespace
when(appNamespaceRepository.findFirst500ByIdGreaterThanOrderByIdAsc(somePublicNamespaceId))
.thenReturn(Lists.newArrayList(anotherPrivateAppNamespace, yetAnotherPrivateAppNamespace,
anotherPublicAppNamespace));
when(appNamespaceRepository.findAll(appNamespaceIds)).thenReturn(allAppNamespaces);
scanIntervalTimeUnit.sleep(sleepInterval);
check(Lists.newArrayList(somePrivateAppNamespace, yetAnotherPrivateAppNamespace,
anotherPublicAppNamespace), appNamespaceServiceWithCache.findByAppIdAndNamespaces
(someAppId, someAppIdNamespaces));
check(Lists.newArrayList(somePublicAppNamespace, anotherPrivateAppNamespace),
appNamespaceServiceWithCache.findByAppIdAndNamespaces(somePublicAppId,
somePublicAppIdNamespaces));
check(Lists.newArrayList(somePublicAppNamespace, anotherPublicAppNamespace),
appNamespaceServiceWithCache.findPublicNamespacesByNames(publicNamespaces));
// Update name
String somePrivateNamespaceNew = "somePrivateNamespaceNew";
AppNamespace somePrivateAppNamespaceNew = assembleAppNamespace(somePrivateAppNamespace.getId
(), somePrivateAppNamespace.getAppId(), somePrivateNamespaceNew, somePrivateAppNamespace
.isPublic());
somePrivateAppNamespaceNew.setDataChangeLastModifiedTime(newDateWithDelta
(somePrivateAppNamespace.getDataChangeLastModifiedTime(), 1));
// Update appId
String someAppIdNew = "someAppIdNew";
AppNamespace yetAnotherPrivateAppNamespaceNew = assembleAppNamespace
(yetAnotherPrivateAppNamespace.getId(), someAppIdNew, yetAnotherPrivateAppNamespace
.getName(), false);
yetAnotherPrivateAppNamespaceNew.setDataChangeLastModifiedTime(newDateWithDelta
(yetAnotherPrivateAppNamespace.getDataChangeLastModifiedTime(), 1));
// Update isPublic
AppNamespace somePublicAppNamespaceNew = assembleAppNamespace(somePublicAppNamespace
.getId(), somePublicAppNamespace.getAppId(), somePublicAppNamespace.getName(),
!somePublicAppNamespace.isPublic());
somePublicAppNamespaceNew.setDataChangeLastModifiedTime(newDateWithDelta
(somePublicAppNamespace.getDataChangeLastModifiedTime(), 1));
// Delete 1 private and 1 public
when(appNamespaceRepository.findAll(appNamespaceIds)).thenReturn(Lists.newArrayList
(somePrivateAppNamespaceNew, yetAnotherPrivateAppNamespaceNew, somePublicAppNamespaceNew));
scanIntervalTimeUnit.sleep(sleepInterval);
check(Collections.emptyList(), appNamespaceServiceWithCache
.findByAppIdAndNamespaces(someAppId, someAppIdNamespaces));
check(Lists.newArrayList(somePublicAppNamespaceNew),
appNamespaceServiceWithCache.findByAppIdAndNamespaces(somePublicAppId,
somePublicAppIdNamespaces));
check(Collections.emptyList(),
appNamespaceServiceWithCache.findPublicNamespacesByNames(publicNamespaces));
check(Lists.newArrayList(somePrivateAppNamespaceNew), appNamespaceServiceWithCache
.findByAppIdAndNamespaces(someAppId, Sets.newHashSet(somePrivateNamespaceNew)));
check(Lists.newArrayList(yetAnotherPrivateAppNamespaceNew), appNamespaceServiceWithCache
.findByAppIdAndNamespaces(someAppIdNew, Sets.newHashSet(yetAnotherPrivateNamespace)));
}
private void check(List<AppNamespace> someList, List<AppNamespace> anotherList) {
Collections.sort(someList, appNamespaceComparator);
Collections.sort(anotherList, appNamespaceComparator);
assertEquals(someList, anotherList);
}
private Date newDateWithDelta(Date date, int deltaInSeconds) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.SECOND, deltaInSeconds);
return calendar.getTime();
}
private AppNamespace assembleAppNamespace(long id, String appId, String name, boolean isPublic) {
AppNamespace appNamespace = new AppNamespace();
appNamespace.setId(id);
appNamespace.setAppId(appId);
appNamespace.setName(name);
appNamespace.setPublic(isPublic);
appNamespace.setDataChangeLastModifiedTime(new Date());
return appNamespace;
}
}