8302983: ZoneRulesProvider.registerProvider() twice will remove provider

Reviewed-by: naoto
This commit is contained in:
Madjosz 2023-04-28 16:23:13 +00:00 committed by Naoto Sato
parent 82ccfe3a21
commit f83e7302c1
2 changed files with 70 additions and 24 deletions
src/java.base/share/classes/java/time/zone
test/jdk/java/time/test/java/time/zone

@ -316,10 +316,11 @@ public abstract class ZoneRulesProvider {
Objects.requireNonNull(zoneId, "zoneId");
ZoneRulesProvider old = ZONES.putIfAbsent(zoneId, provider);
if (old != null) {
// restore old state
ZONES.put(zoneId, old);
provider.provideZoneIds().stream()
.forEach(id -> ZONES.remove(id, provider));
if (!old.equals(provider)) {
// restore old state
ZONES.put(zoneId, old);
provider.provideZoneIds().forEach(id -> ZONES.remove(id, provider));
}
throw new ZoneRulesException(
"Unable to register zone as one already registered with that ID: " + zoneId +
", currently loading from provider: " + provider);

@ -34,46 +34,33 @@ import java.util.Set;
import org.testng.annotations.Test;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
/**
* @summary Tests for ZoneRulesProvider class.
* @bug 8299571
* @bug 8299571 8302983
*/
@Test
public class TestZoneRulesProvider {
private static final Set<String> MY_ZONE_IDS =
new LinkedHashSet(Arrays.asList(new String[] {"MyID_1", "MyID_2", "CET", "MyID_3"}));
/**
* Tests whether partially registered zones are cleaned on a provider registration
* failure, in case a duplicated zone is detected.
* @bug 8299571
*/
@Test
public void test_registerDuplicatedZone() {
Set<String> myZoneIds = new LinkedHashSet<>(Arrays.asList(new String[] {"MyID_1", "MyID_2", "CET", "MyID_3"}));
try {
ZoneRulesProvider.registerProvider(new ZoneRulesProvider() {
@Override
protected Set<String> provideZoneIds() {
return MY_ZONE_IDS;
}
@Override
protected ZoneRules provideRules(String zoneId, boolean forCaching) {
return null;
}
@Override
protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) {
return null;
}
});
ZoneRulesProvider.registerProvider(new IdsOnlyZoneRulesProvider(myZoneIds));
throw new RuntimeException("Registering a provider that duplicates a zone should throw an exception");
} catch (ZoneRulesException e) {
// Ignore. Failure on registration is expected.
}
MY_ZONE_IDS.stream().forEach(id -> {
myZoneIds.stream().forEach(id -> {
var isCET = id.equals("CET");
// availability check
@ -91,4 +78,62 @@ public class TestZoneRulesProvider {
}
});
}
/**
* Tests whether registering a provider twice will still leave it registered.
* @bug 8302983
*/
@Test
public void test_registerTwice() {
String zone = "MyID";
var provider = new IdsOnlyZoneRulesProvider(Set.of(zone));
assertFalse(ZoneId.getAvailableZoneIds().contains(zone), "Unexpected availability for " + zone);
ZoneRulesProvider.registerProvider(provider);
assertTrue(ZoneId.getAvailableZoneIds().contains(zone), "Unexpected non-availability for " + zone);
try {
ZoneId.of(zone);
} catch (ZoneRulesException e) {
fail("ZoneId instance for " + zone + " should be obtainable");
}
try {
ZoneRulesProvider.registerProvider(provider);
fail("Registering an already registered provider should throw an exception");
} catch (ZoneRulesException e) {
// Ignore. Failure on duplicate registration is expected.
}
// availability check
assertTrue(ZoneId.getAvailableZoneIds().contains(zone), "Unexpected non-availability for " + zone);
// instantiation check
try {
ZoneId.of(zone);
} catch (ZoneRulesException e) {
fail("ZoneId instance for " + zone + " should still be obtainable", e);
}
}
private static class IdsOnlyZoneRulesProvider extends ZoneRulesProvider {
private final Set<String> zones;
IdsOnlyZoneRulesProvider(Set<String> zones) {
this.zones = zones;
}
@Override
protected Set<String> provideZoneIds() {
return zones;
}
@Override
protected ZoneRules provideRules(String zoneId, boolean forCaching) {
return null;
}
@Override
protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) {
return null;
}
}
}