Commit 04781220 authored by figroc's avatar figroc Committed by GitHub

Allow repeatable deletions and enhance thread safety (#3069)

parent 4d56835c
...@@ -5,14 +5,13 @@ import com.ctrip.framework.apollo.core.dto.ApolloConfig; ...@@ -5,14 +5,13 @@ import com.ctrip.framework.apollo.core.dto.ApolloConfig;
import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification; import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;
import com.ctrip.framework.apollo.core.utils.ResourceUtils; import com.ctrip.framework.apollo.core.utils.ResourceUtils;
import com.ctrip.framework.apollo.internals.ConfigServiceLocator; import com.ctrip.framework.apollo.internals.ConfigServiceLocator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
...@@ -38,8 +37,8 @@ public class EmbeddedApollo extends ExternalResource { ...@@ -38,8 +37,8 @@ public class EmbeddedApollo extends ExternalResource {
private static ConfigServiceLocator CONFIG_SERVICE_LOCATOR; private static ConfigServiceLocator CONFIG_SERVICE_LOCATOR;
private final Gson gson = new Gson(); private final Gson gson = new Gson();
private final Map<String, Map<String, String>> addedOrModifiedPropertiesOfNamespace = new HashMap<>(); private final Map<String, Map<String, String>> addedOrModifiedPropertiesOfNamespace = Maps.newConcurrentMap();
private final Map<String, Set<String>> deletedKeysOfNamespace = new HashMap<>(); private final Map<String, Set<String>> deletedKeysOfNamespace = Maps.newConcurrentMap();
private MockWebServer server; private MockWebServer server;
...@@ -151,7 +150,7 @@ public class EmbeddedApollo extends ExternalResource { ...@@ -151,7 +150,7 @@ public class EmbeddedApollo extends ExternalResource {
if (addedOrModifiedPropertiesOfNamespace.containsKey(namespace)) { if (addedOrModifiedPropertiesOfNamespace.containsKey(namespace)) {
addedOrModifiedPropertiesOfNamespace.get(namespace).put(someKey, someValue); addedOrModifiedPropertiesOfNamespace.get(namespace).put(someKey, someValue);
} else { } else {
Map<String, String> m = new HashMap<>(); Map<String, String> m = Maps.newConcurrentMap();
m.put(someKey, someValue); m.put(someKey, someValue);
addedOrModifiedPropertiesOfNamespace.put(namespace, m); addedOrModifiedPropertiesOfNamespace.put(namespace, m);
} }
...@@ -164,7 +163,9 @@ public class EmbeddedApollo extends ExternalResource { ...@@ -164,7 +163,9 @@ public class EmbeddedApollo extends ExternalResource {
if (deletedKeysOfNamespace.containsKey(namespace)) { if (deletedKeysOfNamespace.containsKey(namespace)) {
deletedKeysOfNamespace.get(namespace).add(someKey); deletedKeysOfNamespace.get(namespace).add(someKey);
} else { } else {
deletedKeysOfNamespace.put(namespace, ImmutableSet.of(someKey)); Set<String> m = Sets.newConcurrentHashSet();
m.add(someKey);
deletedKeysOfNamespace.put(namespace, m);
} }
} }
......
package com.ctrip.framework.apollo.mockserver; package com.ctrip.framework.apollo.mockserver;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.Config;
...@@ -8,7 +9,10 @@ import com.ctrip.framework.apollo.ConfigChangeListener; ...@@ -8,7 +9,10 @@ import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService; import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent; import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.ClassRule; import org.junit.ClassRule;
import org.junit.Test; import org.junit.Test;
...@@ -51,7 +55,79 @@ public class ApolloMockServerApiTest { ...@@ -51,7 +55,79 @@ public class ApolloMockServerApiTest {
assertEquals(someNewValue, otherConfig.getProperty("key1", null)); assertEquals(someNewValue, otherConfig.getProperty("key1", null));
assertEquals("otherValue2", otherConfig.getProperty("key2", null)); assertEquals("otherValue2", otherConfig.getProperty("key2", null));
assertTrue(changeEvent.isChanged("key1")); assertTrue(changeEvent.isChanged("key1"));
} }
@Test
public void testUpdateSamePropertyTwice() throws Exception {
String someNewValue = "someNewValue";
Config otherConfig = ConfigService.getConfig(anotherNamespace);
final Semaphore changes = new Semaphore(0);
otherConfig.addChangeListener(new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
changes.release();
}
});
assertEquals("otherValue3", otherConfig.getProperty("key3", null));
embeddedApollo.addOrModifyProperty(anotherNamespace, "key3", someNewValue);
embeddedApollo.addOrModifyProperty(anotherNamespace, "key3", someNewValue);
assertTrue(changes.tryAcquire(5, TimeUnit.SECONDS));
assertEquals(someNewValue, otherConfig.getProperty("key3", null));
assertEquals(0, changes.availablePermits());
}
@Test
public void testDeleteProperties() throws Exception {
Config otherConfig = ConfigService.getConfig(anotherNamespace);
final SettableFuture<ConfigChangeEvent> future = SettableFuture.create();
otherConfig.addChangeListener(new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
future.set(changeEvent);
}
});
assertEquals("otherValue4", otherConfig.getProperty("key4", null));
assertEquals("otherValue5", otherConfig.getProperty("key5", null));
embeddedApollo.deleteProperty(anotherNamespace, "key4");
ConfigChangeEvent changeEvent = future.get(5, TimeUnit.SECONDS);
assertNull(otherConfig.getProperty("key4", null));
assertEquals("otherValue5", otherConfig.getProperty("key5", null));
assertTrue(changeEvent.isChanged("key4"));
}
@Test
public void testDeleteSamePropertyTwice() throws Exception {
Config otherConfig = ConfigService.getConfig(anotherNamespace);
final Semaphore changes = new Semaphore(0);
otherConfig.addChangeListener(new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
changes.release();
}
});
assertEquals("otherValue6", otherConfig.getProperty("key6", null));
embeddedApollo.deleteProperty(anotherNamespace, "key6");
embeddedApollo.deleteProperty(anotherNamespace, "key6");
assertTrue(changes.tryAcquire(5, TimeUnit.SECONDS));
assertNull(otherConfig.getProperty("key6", null));
assertEquals(0, changes.availablePermits());
}
} }
key1=otherValue1 key1=otherValue1
key2=otherValue2 key2=otherValue2
key3=otherValue3
key4=otherValue4
key5=otherValue5
key6=otherValue6
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment