Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow repeatable deletions and enhance thread safety #3069

Merged
merged 3 commits into from
May 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;
import com.ctrip.framework.apollo.core.utils.ResourceUtils;
import com.ctrip.framework.apollo.internals.ConfigServiceLocator;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
Expand All @@ -38,8 +37,8 @@ public class EmbeddedApollo extends ExternalResource {
private static ConfigServiceLocator CONFIG_SERVICE_LOCATOR;

private final Gson gson = new Gson();
private final Map<String, Map<String, String>> addedOrModifiedPropertiesOfNamespace = new HashMap<>();
private final Map<String, Set<String>> deletedKeysOfNamespace = new HashMap<>();
private final Map<String, Map<String, String>> addedOrModifiedPropertiesOfNamespace = Maps.newConcurrentMap();
private final Map<String, Set<String>> deletedKeysOfNamespace = Maps.newConcurrentMap();

private MockWebServer server;

Expand Down Expand Up @@ -151,7 +150,7 @@ public void addOrModifyProperty(String namespace, String someKey, String someVal
if (addedOrModifiedPropertiesOfNamespace.containsKey(namespace)) {
addedOrModifiedPropertiesOfNamespace.get(namespace).put(someKey, someValue);
} else {
Map<String, String> m = new HashMap<>();
Map<String, String> m = Maps.newConcurrentMap();
m.put(someKey, someValue);
addedOrModifiedPropertiesOfNamespace.put(namespace, m);
}
Expand All @@ -164,7 +163,9 @@ public void deleteProperty(String namespace, String someKey) {
if (deletedKeysOfNamespace.containsKey(namespace)) {
deletedKeysOfNamespace.get(namespace).add(someKey);
} else {
deletedKeysOfNamespace.put(namespace, ImmutableSet.of(someKey));
Set<String> m = Sets.newConcurrentHashSet();
m.add(someKey);
deletedKeysOfNamespace.put(namespace, m);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package com.ctrip.framework.apollo.mockserver;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.google.common.util.concurrent.SettableFuture;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.junit.ClassRule;
import org.junit.Test;

Expand Down Expand Up @@ -51,7 +55,79 @@ public void onChange(ConfigChangeEvent changeEvent) {

assertEquals(someNewValue, otherConfig.getProperty("key1", null));
assertEquals("otherValue2", otherConfig.getProperty("key2", null));

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());
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
key1=otherValue1
key2=otherValue2
key3=otherValue3
key4=otherValue4
key5=otherValue5
key6=otherValue6