Skip to content

Commit

Permalink
Add some more tests / create util method for empty check
Browse files Browse the repository at this point in the history
  • Loading branch information
ljacqu committed Sep 11, 2023
1 parent 7b1c665 commit 1066a5c
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,7 @@ public ArrayPropertyBuilder(@NotNull BiFunction<String, E[], P> createPropertyFu
*/
@SafeVarargs
public final @NotNull ArrayPropertyBuilder<E, P> defaultValue(@NotNull E @NotNull ... entries) {
if (!defaultValue.isEmpty()) {
throw new IllegalStateException("Default values have already been defined! Use addToDefaultValue "
+ "to add entries individually");
}

PropertyBuilderUtils.verifyDefaultValueIsEmpty(defaultValue.isEmpty());
defaultValue.addAll(Arrays.asList(entries));
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,7 @@ public CollectionPropertyBuilder(@NotNull BiFunction<String, C, P> createPropert
*/
@SafeVarargs
public final @NotNull CollectionPropertyBuilder<E, C, P> defaultValue(@NotNull E @NotNull ... entries) {
if (!defaultValue.isEmpty()) {
throw new IllegalStateException("Default values have already been defined! Use addToDefaultValue "
+ "to add entries individually");
}

defaultValue.addAll(Arrays.asList(entries));
return this;
return defaultValue(Arrays.asList(entries));
}

/**
Expand All @@ -118,11 +112,7 @@ public CollectionPropertyBuilder(@NotNull BiFunction<String, C, P> createPropert
* @return this builder
*/
public @NotNull CollectionPropertyBuilder<E, C, P> defaultValue(@NotNull Collection<? extends E> entries) {
if (!defaultValue.isEmpty()) {
throw new IllegalStateException("Default values have already been defined! Use addToDefaultValue "
+ "to add entries individually");
}

PropertyBuilderUtils.verifyDefaultValueIsEmpty(defaultValue.isEmpty());
defaultValue.addAll(entries);
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,37 @@
import java.util.Map;
import java.util.function.BiFunction;

/**
* Builder for map properties whose keys are string and whose value type is any arbitrary property type.
*
* @param <V> the type of the values in the map
* @param <M> the map type
* @param <P> the property type
*/
public class MapPropertyBuilder<V, M extends Map<String, V>, P extends Property<M>> {

private String path;
private final M defaultValue;
private final BiFunction<String, M, P> createPropertyFunction;

/**
* Constructor. Prefer using the static method {@link #mapBuilder} when possible.
*
* @param createPropertyFunction function taking path and default value and returning a property
* @param defaultValue empty, mutable map that contains the default values (added by builder methods)
*/
public MapPropertyBuilder(@NotNull BiFunction<String, M, P> createPropertyFunction, @NotNull M defaultValue) {
this.createPropertyFunction = createPropertyFunction;
this.defaultValue = defaultValue;
}

/**
* Creates a new map property builder to construct an object of ConfigMe's standard MapProperty implementation.
*
* @param entryType the type the values in the map have
* @param <V> the type of the values in the map
* @return this instance
*/
public static <V> @NotNull MapPropertyBuilder<V, Map<String, V>, MapProperty<V>> mapBuilder(
@NotNull PropertyType<V> entryType) {
return new MapPropertyBuilder<>(
Expand All @@ -43,9 +63,8 @@ public MapPropertyBuilder(@NotNull BiFunction<String, M, P> createPropertyFuncti
return this;
}

// TODO: Here and in other builders, disallow both types of default value setting to be used in same builder?
public @NotNull MapPropertyBuilder<V, M, P> defaultValue(@NotNull Map<String, V> defaultValue) {
this.defaultValue.clear();
PropertyBuilderUtils.verifyDefaultValueIsEmpty(this.defaultValue.isEmpty());
this.defaultValue.putAll(defaultValue);
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,17 @@ static void requireNonNullPath(@Nullable String path) {
throw new IllegalStateException("The path of the property must be defined");
}
}

/**
* Throws an exception referring to the method {@code addToDefaultValue} if the provided parameter indicates that
* the default value collection/map is not empty.
*
* @param isEmpty whether the default value (collection/map) is currently empty
*/
static void verifyDefaultValueIsEmpty(boolean isEmpty) {
if (!isEmpty) {
throw new IllegalStateException("Default values have already been defined! Use addToDefaultValue "
+ "to add entries individually");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ public InlineArrayPropertyType(@NotNull PropertyType<T> entryType, @NotNull Stri
return null;
}

/**
* Converts the given element to the appropriate type, or registers an error and returns null if not possible.
*
* @param entry the entry to convert
* @param errorRecorder recorder to add errors to
* @return the converted entry if possible, otherwise null
*/
protected @Nullable T convertOrRegisterError(@NotNull String entry, @NotNull ConvertErrorRecorder errorRecorder) {
T value = useTrimAndSpaces
? entryType.convert(entry.trim(), errorRecorder)
Expand All @@ -88,6 +95,9 @@ public InlineArrayPropertyType(@NotNull PropertyType<T> entryType, @NotNull Stri
.collect(Collectors.joining(delimiter));
}

/**
* @return function to create an array with the given capacity
*/
public IntFunction<T[]> getArrayProducer() {
return arrayProducer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.mockito.junit.jupiter.MockitoExtension;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -49,4 +50,21 @@ void shouldReturnConvertedValueAsExportValue() {
// when / then
assertThat(property.toExportValue(given), equalTo("hello, chert\nhow in hell?"));
}

@Test
void shouldLogErrorForFailedConversion() {
// given
String value = "3,four,5";
InlineArrayProperty<Integer> property = new InlineArrayProperty<>("path", new Integer[0], InlineArrayPropertyType.INTEGER);
ConvertErrorRecorder errorRecorder = new ConvertErrorRecorder();
PropertyReader reader = mock(PropertyReader.class);
given(reader.getObject("path")).willReturn(value);

// when
Integer[] result = property.getFromReader(reader, errorRecorder);

// then
assertThat(result, arrayContaining(3, 5));
assertThat(errorRecorder.isFullyValid(), equalTo(false));
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package ch.jalu.configme.properties.builder;

import ch.jalu.configme.properties.ArrayProperty;
import ch.jalu.configme.properties.InlineArrayProperty;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.properties.types.BooleanType;
import ch.jalu.configme.properties.types.InlineArrayPropertyType;
import ch.jalu.configme.properties.types.NumberType;
import org.junit.jupiter.api.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.emptyArray;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
* Test for {@link ArrayPropertyBuilder}.
Expand All @@ -27,4 +34,57 @@ void shouldCreateInlineArrayProperty() {
assertThat(property.getDefaultValue(), arrayContaining(-1.23f));
}

@Test
void shouldCreateArrayProperty() {
// given / when
Property<Long[]> property = ArrayPropertyBuilder.arrayBuilder(NumberType.LONG, Long[]::new)
.path("given.path")
.defaultValue(5L, 11L, 23L)
.build();

// then
assertThat(property, instanceOf(ArrayProperty.class));
assertThat(property.getPath(), equalTo("given.path"));
assertThat(property.getDefaultValue(), arrayContaining(5L, 11L, 23L));
}

@Test
void shouldCreateArrayWithDefaultValueSuccessivelyAddedTo() {
// given / when
ArrayProperty<Long> property = ArrayPropertyBuilder.arrayBuilder(NumberType.LONG.arrayType())
.path("the.path")
.addToDefaultValue(3L)
.addToDefaultValue(7L)
.addToDefaultValue(13L)
.build();

// then
assertThat(property.getDefaultValue(), arrayContaining(3L, 7L, 13L));
assertThat(property.getPath(), equalTo("the.path"));
}

@Test
void shouldThrowIfNonEmptyDefaultValueIsOverridden() {
// given
ArrayPropertyBuilder<Double, ArrayProperty<Double>> builder = ArrayPropertyBuilder.arrayBuilder(NumberType.DOUBLE.arrayType())
.addToDefaultValue(3.0)
.path("soap");

// when
IllegalStateException ex = assertThrows(IllegalStateException.class, () -> builder.defaultValue(4.0));

// then
assertThat(ex.getMessage(), equalTo("Default values have already been defined! Use addToDefaultValue to add entries individually"));
}

@Test
void shouldCreateArrayPropertyWithEmptyDefault() {
// given / when
ArrayProperty<Boolean> property = ArrayPropertyBuilder.arrayBuilder(BooleanType.BOOLEAN.arrayType())
.path("filters")
.build();

// then
assertThat(property.getDefaultValue(), emptyArray());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@
import ch.jalu.configme.properties.ListProperty;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.properties.SetProperty;
import ch.jalu.configme.properties.types.BooleanType;
import ch.jalu.configme.properties.types.EnumPropertyType;
import ch.jalu.configme.properties.types.NumberType;
import ch.jalu.configme.properties.types.StringType;
import ch.jalu.configme.samples.TestEnum;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static ch.jalu.configme.TestUtils.getExceptionTypeForNullArg;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -53,12 +57,53 @@ void shouldCreateSetProperty() {
}

@Test
@Disabled // TODO: Throw, or allow for empty list?
void shouldThrowForMissingDefaultValue() {
// given / when / then
assertThrows(getExceptionTypeForNullArg(),
() -> CollectionPropertyBuilder.listBuilder(NumberType.DOUBLE)
.path("defined.path")
.build());
void shouldAllowEmptyDefaultValue() {
// given / when
ListProperty<Double> property = CollectionPropertyBuilder.listBuilder(NumberType.DOUBLE)
.path("defined.path")
.build();

// then
assertThat(property.getDefaultValue(), empty());
}

@Test
void shouldThrowIfNonEmptyDefaultValueIsOverwritten() {
// given
CollectionPropertyBuilder<String, ?, SetProperty<String>> builder = CollectionPropertyBuilder.setBuilder(StringType.STRING_LOWER_CASE)
.addToDefaultValue("name");

// when
IllegalStateException ex = assertThrows(IllegalStateException.class, () -> builder.defaultValue("test"));

// then
assertThat(ex.getMessage(), equalTo("Default values have already been defined! Use addToDefaultValue to add entries individually"));
}

@Test
void shouldThrowExceptionForMissingPath() {
// given / when
IllegalStateException ex = assertThrows(IllegalStateException.class, () -> CollectionPropertyBuilder.listBuilder(BooleanType.BOOLEAN)
.defaultValue(true, false)
.build());

// then
assertThat(ex.getMessage(), equalTo("The path of the property must be defined"));
}

@Test
void shouldCreateListPropertyWithTheGivenDefaultValue() {
// given
List<Integer> defaultWeights = Arrays.asList(7, 11, 2);

// when
SetProperty<Integer> property = CollectionPropertyBuilder.setBuilder(NumberType.INTEGER)
.defaultValue(defaultWeights)
.path("weights")
.build();

// then
assertThat(property.getPath(), equalTo("weights"));
assertThat(property.getDefaultValue(), contains(7, 11, 2)); // Set property uses a LinkedHashSet, so check concrete order
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

import ch.jalu.configme.properties.MapProperty;
import ch.jalu.configme.properties.types.NumberType;
import ch.jalu.configme.properties.types.StringType;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;

/**
Expand Down Expand Up @@ -52,6 +57,41 @@ void shouldThrowForMissingPathInMapBuilder() {
() -> MapPropertyBuilder.mapBuilder(NumberType.DOUBLE).build());

// then
assertThat(ex.getMessage(), equalTo("The path was not defined"));
assertThat(ex.getMessage(), equalTo("The path of the property must be defined"));
}

@Test
void shouldThrowIfNonEmptyDefaultValueIsOverwritten() {
// given
MapPropertyBuilder<String, ?, MapProperty<String>> builder = MapPropertyBuilder.mapBuilder(StringType.STRING)
.path("aliases")
.addToDefaultValue("cd", "dir");
Map<String, String> newDefaultValues = new HashMap<>();

// when
IllegalStateException ex = assertThrows(IllegalStateException.class,
() -> builder.defaultValue(newDefaultValues));

// then
assertThat(ex.getMessage(), equalTo("Default values have already been defined! Use addToDefaultValue to add entries individually"));
}

@Test
void shouldCreatePropertyWithDefaultValueFromOtherMap() {
// given
TreeMap<String, Integer> defaultValues = new TreeMap<>();
defaultValues.put("three", 3);
defaultValues.put("four", 4);
defaultValues.put("one", 1);

// when
MapProperty<Integer> property = MapPropertyBuilder.mapBuilder(NumberType.INTEGER)
.defaultValue(defaultValues)
.path("translations")
.build();

// then
assertThat(property.getPath(), equalTo("translations"));
assertThat(property.getDefaultValue().keySet(), contains("four", "one", "three")); // TreeSet keeps its keys sorted
}
}

0 comments on commit 1066a5c

Please sign in to comment.