Skip to content

Commit

Permalink
Merge branch 'master' into additional-sources
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez authored Nov 3, 2020
2 parents 9b0f5b8 + 310727d commit ba30650
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ public A convert(final String str) {
for (String itemString : itemStrings) {
if (!itemString.isEmpty()) {
final T item = getDelegate().convert(itemString);
if (item != null && !item.equals(",")) {
if (item != null) {
Array.set(array, size++, item);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static java.security.AccessController.doPrivileged;
import static java.util.Collections.unmodifiableMap;

import java.io.Serializable;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
Expand All @@ -31,9 +32,11 @@
*/
public class EnvConfigSource extends AbstractConfigSource {
private static final long serialVersionUID = -4525015934376795496L;

private static final int DEFAULT_ORDINAL = 300;
private static final Object NULL_VALUE = new Object();

private final Map<String, String> cache = new ConcurrentHashMap<>(); //the regex match is expensive
private final Map<String, Object> cache = new ConcurrentHashMap<>();

protected EnvConfigSource() {
super("EnvConfigSource", getEnvOrdinal());
Expand All @@ -50,9 +53,12 @@ public String getValue(String name) {
return null;
}

String cachedValue = cache.get(name);
Object cachedValue = cache.get(name);
if (cachedValue != null) {
return cachedValue;
if (cachedValue == NULL_VALUE) {
return null;
}
return (String) cachedValue;
}

final Map<String, String> properties = getProperties();
Expand Down Expand Up @@ -80,6 +86,7 @@ public String getValue(String name) {
return value;
}

cache.put(name, NULL_VALUE);
return null;
}

Expand Down Expand Up @@ -133,4 +140,16 @@ private static int getEnvOrdinal() {

return DEFAULT_ORDINAL;
}

Object writeReplace() {
return new Ser();
}

static final class Ser implements Serializable {
private static final long serialVersionUID = 6812312718645271331L;

Object readResolve() {
return new EnvConfigSource();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,118 +2,125 @@

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Optional;

import org.junit.jupiter.api.Test;

// https://github.com/eclipse/microprofile-config/issues/446
// https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configexamples.asciidoc#config-value-conversion-rules
class EmptyValuesTest {
@Test // Rule 1
@Test
void missingForArray() {
assertThrows(NoSuchElementException.class, () -> config().getValue("my.prop", String[].class));
}

@Test // Rule 2
@Test
void emptyForArray() {
assertThrows(NoSuchElementException.class, () -> config("my.prop", "").getValue("my.prop", String[].class));
}

@Test // Rule 3
@Test
void commaForArray() {
assertThrows(NoSuchElementException.class, () -> config("my.prop", ",").getValue("my.prop", String[].class));
assertThrows(NoSuchElementException.class, () -> config("my.prop", "\\,").getValue("my.prop", String[].class));
assertArrayEquals(new String[] { "," }, config("my.prop", "\\,").getValue("my.prop", String[].class));
}

@Test // Rule 4
@Test
void multipleCommasForArray() {
assertThrows(NoSuchElementException.class, () -> config("my.prop", ",,").getValue("my.prop", String[].class));
}

@Test // Rule 5
@Test
void valuesForArray() {
assertArrayEquals(new String[] { "foo", "bar" }, config("my.prop", "foo,bar").getValue("my.prop", String[].class));
}

@Test // Rule 6
@Test
void valuesCommaEndForArray() {
assertArrayEquals(new String[] { "foo" }, config("my.prop", "foo,").getValue("my.prop", String[].class));
}

@Test // Rule 7
@Test
void valuesCommaStartForArray() {
assertArrayEquals(new String[] { "bar" }, config("my.prop", ",bar").getValue("my.prop", String[].class));
}

@Test // Rule 8
@Test
void whitespaceForArray() {
assertArrayEquals(new String[] { " " }, config("my.prop", " ").getValue("my.prop", String[].class));
}

@Test // Rule 9
@Test
void value() {
assertEquals("foo", config("my.prop", "foo").getValue("my.prop", String.class));
}

@Test // Rule 10
@Test
void empty() {
assertThrows(NoSuchElementException.class, () -> config("my.prop", "").getValue("my.prop", String.class));
}

@Test // Rule 11
@Test
void comma() {
assertEquals(",", config("my.prop", ",").getValue("my.prop", String.class));
}

@Test // Rule 12
@Test
void missing() {
assertThrows(NoSuchElementException.class, () -> config().getValue("my.prop", String.class));
}

@Test // Rule 13
@Test
void valueForOptional() {
assertEquals(Optional.of("foo"), config("my.prop", "foo").getOptionalValue("my.prop", String.class));
}

@Test // Rule 14
@Test
void emptyForOptional() {
assertEquals(Optional.empty(), config("my.prop", "").getOptionalValue("my.prop", String.class));
assertNotEquals(Optional.of(""), config("my.prop", "").getOptionalValue("my.prop", String.class));
}

@Test // Rule 15
@Test
void missingForOptional() {
assertEquals(Optional.empty(), config().getOptionalValue("my.prop", String.class));
}

@Test // Rule 16
@Test
void emptyForOptionalArray() {
assertEquals(Optional.empty(), config("my.prop", "").getOptionalValue("my.prop", String[].class));
assertNotEquals(Optional.of(new String[] {}), config("my.prop", "").getOptionalValue("my.prop", String[].class));
}

@Test // Rule 17
@Test
void commaForOptionalArray() {
assertEquals(Optional.empty(), config("my.prop", ",").getOptionalValue("my.prop", String[].class));
assertNotEquals(Optional.of(new String[] { "", "" }),
config("my.prop", ",").getOptionalValue("my.prop", String[].class));
assertTrue(config("my.prop", "\\,").getOptionalValue("my.prop", String[].class).isPresent());
assertArrayEquals(new String[] { "," }, config("my.prop", "\\,").getOptionalValue("my.prop", String[].class).get());
assertFalse(config("my.prop", ",").getOptionalValue("my.prop", String[].class).isPresent());
}

@Test // Rule 18
@Test
void mutipleCommasForOptionalArray() {
assertEquals(Optional.empty(), config("my.prop", ",,").getOptionalValue("my.prop", String[].class));
assertNotEquals(Optional.of(new String[] { "", "", "" }),
config("my.prop", ",").getOptionalValue("my.prop", String[].class));
}

@Test // Rule 19
@Test
void missingForOptionalArray() {
assertEquals(Optional.empty(), config().getOptionalValue("my.prop", String[].class));
}

@Test
void commaForOptionalList() {
assertTrue(config("my.prop", "\\,").getOptionalValues("my.prop", String.class, ArrayList::new).isPresent());
}

private static SmallRyeConfig config(String... keyValues) {
return new SmallRyeConfigBuilder()
.addDefaultInterceptors()
Expand Down

0 comments on commit ba30650

Please sign in to comment.