package com.ctrip.framework.apollo.configservice.controller; import com.google.common.cache.Cache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.ctrip.framework.apollo.biz.entity.ReleaseMessage; import com.ctrip.framework.apollo.biz.grayReleaseRule.GrayReleaseRulesHolder; import com.ctrip.framework.apollo.biz.message.Topics; import com.ctrip.framework.apollo.configservice.util.NamespaceUtil; import com.ctrip.framework.apollo.configservice.util.WatchKeysUtil; import com.ctrip.framework.apollo.core.dto.ApolloConfig; 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.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.util.ReflectionTestUtils; import java.lang.reflect.Type; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** * @author Jason Song(song_s@ctrip.com) */ @RunWith(MockitoJUnitRunner.class) public class ConfigFileControllerTest { @Mock private ConfigController configController; @Mock private WatchKeysUtil watchKeysUtil; @Mock private NamespaceUtil namespaceUtil; @Mock private GrayReleaseRulesHolder grayReleaseRulesHolder; private ConfigFileController configFileController; private String someAppId; private String someClusterName; private String someNamespace; private String someDataCenter; private String someClientIp; @Mock private HttpServletResponse someResponse; @Mock private HttpServletRequest someRequest; Multimap<String, String> watchedKeys2CacheKey; Multimap<String, String> cacheKey2WatchedKeys; @Before public void setUp() throws Exception { configFileController = new ConfigFileController(); ReflectionTestUtils.setField(configFileController, "configController", configController); ReflectionTestUtils.setField(configFileController, "watchKeysUtil", watchKeysUtil); ReflectionTestUtils.setField(configFileController, "namespaceUtil", namespaceUtil); ReflectionTestUtils.setField(configFileController, "grayReleaseRulesHolder", grayReleaseRulesHolder); someAppId = "someAppId"; someClusterName = "someClusterName"; someNamespace = "someNamespace"; someDataCenter = "someDataCenter"; someClientIp = "10.1.1.1"; when(namespaceUtil.filterNamespaceName(someNamespace)).thenReturn(someNamespace); when(grayReleaseRulesHolder.hasGrayReleaseRule(anyString(), anyString(), anyString())) .thenReturn(false); watchedKeys2CacheKey = (Multimap<String, String>) ReflectionTestUtils .getField(configFileController, "watchedKeys2CacheKey"); cacheKey2WatchedKeys = (Multimap<String, String>) ReflectionTestUtils .getField(configFileController, "cacheKey2WatchedKeys"); } @Test public void testQueryConfigAsProperties() throws Exception { String someKey = "someKey"; String someValue = "someValue"; String anotherKey = "anotherKey"; String anotherValue = "anotherValue"; String someWatchKey = "someWatchKey"; String anotherWatchKey = "anotherWatchKey"; Set<String> watchKeys = Sets.newHashSet(someWatchKey, anotherWatchKey); String cacheKey = configFileController .assembleCacheKey(ConfigFileController.ConfigFileOutputFormat.PROPERTIES, someAppId, someClusterName, someNamespace, someDataCenter); Map<String, String> configurations = ImmutableMap.of(someKey, someValue, anotherKey, anotherValue); ApolloConfig someApolloConfig = mock(ApolloConfig.class); when(someApolloConfig.getConfigurations()).thenReturn(configurations); when(configController .queryConfig(someAppId, someClusterName, someNamespace, someDataCenter, "-1", someClientIp, someRequest, someResponse)).thenReturn(someApolloConfig); when(watchKeysUtil .assembleAllWatchKeys(someAppId, someClusterName, someNamespace, someDataCenter)) .thenReturn(watchKeys); ResponseEntity<String> response = configFileController .queryConfigAsProperties(someAppId, someClusterName, someNamespace, someDataCenter, someClientIp, someRequest, someResponse); assertEquals(2, watchedKeys2CacheKey.size()); assertEquals(2, cacheKey2WatchedKeys.size()); assertTrue(watchedKeys2CacheKey.containsEntry(someWatchKey, cacheKey)); assertTrue(watchedKeys2CacheKey.containsEntry(anotherWatchKey, cacheKey)); assertTrue(cacheKey2WatchedKeys.containsEntry(cacheKey, someWatchKey)); assertTrue(cacheKey2WatchedKeys.containsEntry(cacheKey, anotherWatchKey)); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response.getBody().contains(String.format("%s=%s", someKey, someValue))); assertTrue(response.getBody().contains(String.format("%s=%s", anotherKey, anotherValue))); ResponseEntity<String> anotherResponse = configFileController .queryConfigAsProperties(someAppId, someClusterName, someNamespace, someDataCenter, someClientIp, someRequest, someResponse); assertEquals(response, anotherResponse); verify(configController, times(1)) .queryConfig(someAppId, someClusterName, someNamespace, someDataCenter, "-1", someClientIp, someRequest, someResponse); } @Test public void testQueryConfigAsJson() throws Exception { String someKey = "someKey"; String someValue = "someValue"; Gson gson = new Gson(); Type responseType = new TypeToken<Map<String, String>>(){}.getType(); String someWatchKey = "someWatchKey"; Set<String> watchKeys = Sets.newHashSet(someWatchKey); Map<String, String> configurations = ImmutableMap.of(someKey, someValue); ApolloConfig someApolloConfig = mock(ApolloConfig.class); when(configController .queryConfig(someAppId, someClusterName, someNamespace, someDataCenter, "-1", someClientIp, someRequest, someResponse)).thenReturn(someApolloConfig); when(someApolloConfig.getConfigurations()).thenReturn(configurations); when(watchKeysUtil .assembleAllWatchKeys(someAppId, someClusterName, someNamespace, someDataCenter)) .thenReturn(watchKeys); ResponseEntity<String> response = configFileController .queryConfigAsJson(someAppId, someClusterName, someNamespace, someDataCenter, someClientIp, someRequest, someResponse); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(configurations, gson.fromJson(response.getBody(), responseType)); } @Test public void testQueryConfigWithGrayRelease() throws Exception { String someKey = "someKey"; String someValue = "someValue"; Gson gson = new Gson(); Type responseType = new TypeToken<Map<String, String>>(){}.getType(); Map<String, String> configurations = ImmutableMap.of(someKey, someValue); when(grayReleaseRulesHolder.hasGrayReleaseRule(someAppId, someClientIp, someNamespace)) .thenReturn(true); ApolloConfig someApolloConfig = mock(ApolloConfig.class); when(someApolloConfig.getConfigurations()).thenReturn(configurations); when(configController .queryConfig(someAppId, someClusterName, someNamespace, someDataCenter, "-1", someClientIp, someRequest, someResponse)).thenReturn(someApolloConfig); ResponseEntity<String> response = configFileController .queryConfigAsJson(someAppId, someClusterName, someNamespace, someDataCenter, someClientIp, someRequest, someResponse); ResponseEntity<String> anotherResponse = configFileController .queryConfigAsJson(someAppId, someClusterName, someNamespace, someDataCenter, someClientIp, someRequest, someResponse); verify(configController, times(2)) .queryConfig(someAppId, someClusterName, someNamespace, someDataCenter, "-1", someClientIp, someRequest, someResponse); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(configurations, gson.fromJson(response.getBody(), responseType)); assertTrue(watchedKeys2CacheKey.isEmpty()); assertTrue(cacheKey2WatchedKeys.isEmpty()); } @Test public void testHandleMessage() throws Exception { String someWatchKey = "someWatchKey"; String anotherWatchKey = "anotherWatchKey"; String someCacheKey = "someCacheKey"; String anotherCacheKey = "anotherCacheKey"; String someValue = "someValue"; ReleaseMessage someReleaseMessage = mock(ReleaseMessage.class); when(someReleaseMessage.getMessage()).thenReturn(someWatchKey); Cache<String, String> cache = (Cache<String, String>) ReflectionTestUtils.getField(configFileController, "localCache"); cache.put(someCacheKey, someValue); cache.put(anotherCacheKey, someValue); watchedKeys2CacheKey.putAll(someWatchKey, Lists.newArrayList(someCacheKey, anotherCacheKey)); watchedKeys2CacheKey.putAll(anotherWatchKey, Lists.newArrayList(someCacheKey, anotherCacheKey)); cacheKey2WatchedKeys.putAll(someCacheKey, Lists.newArrayList(someWatchKey, anotherWatchKey)); cacheKey2WatchedKeys.putAll(anotherCacheKey, Lists.newArrayList(someWatchKey, anotherWatchKey)); configFileController.handleMessage(someReleaseMessage, Topics.APOLLO_RELEASE_TOPIC); assertTrue(watchedKeys2CacheKey.isEmpty()); assertTrue(cacheKey2WatchedKeys.isEmpty()); } }