Skip to content

Commit

Permalink
Increase coverage of value parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
smithkm committed Nov 25, 2023
1 parent 336c266 commit ee2606f
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
public interface OptionalControlMapSubResourceParser<T>
extends ControlMapSubResourceParser<T>, OptionalResourceControlMapModifier {

@Override
default void defaultModify(Map<String, Object> control) {
control.put(getControlKey(), defaultResult());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,20 @@ public boolean isStopLine(String line) {
}.value(3, SC_KEY, PARSE_SC).value(7, COASTAL_KEY, PARSE_AGE).value(7, INTERIOR_KEY, PARSE_AGE)
.value(7, T1_KEY, PARSE_AGE).value(7, T2_KEY, PARSE_AGE);

static ControlledValueParser<Integer> PARSE_SC = ControlledValueParser.validate(ValueParser.INTEGER, (v, c) -> {
if (v < -1 || v > MAX_SC) {
return Optional.of("Site curve number must be in the range -1 to " + MAX_SC + " inclusive");
}
return Optional.empty();
});

static ValueParser<Float> PARSE_AGE = s -> {
static final ControlledValueParser<Integer> PARSE_SC = ControlledValueParser
.validate(ValueParser.INTEGER, (v, c) -> {
if (v < -1 || v > MAX_SC) {
return Optional.of("Site curve number must be in the range -1 to " + MAX_SC + " inclusive");
}
return Optional.empty();
});

static final ValueParser<Float> PARSE_AGE = s -> {
var value = ValueParser.FLOAT.parse(s);
return value <= 0.0 ? MAX_AGE : value;
};

@Override
@SuppressWarnings("serial")
public Map<Integer, SiteCurveAgeMaximum> defaultResult() {
return new HashMap<>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,17 +300,16 @@ static <U> ValueParser<U> uncontrolled(ControlledValueParser<U> delegate) {
* return empty if the string is not a marker.
* @return a ValueOrMarker
*/
public static <Value, Marker> ValueParser<ValueOrMarker<Value, Marker>>
valueOrMarker(ValueParser<Value> valueParser, ValueParser<Optional<Marker>> markerParser) {
public static <V, M> ValueParser<ValueOrMarker<V, M>>
valueOrMarker(ValueParser<V> valueParser, ValueParser<Optional<M>> markerParser) {
return s -> {
var builder = new ValueOrMarker.Builder<Value, Marker>();
var builder = new ValueOrMarker.Builder<V, M>();
var marker = markerParser.parse(s).map(builder::marker);
if (marker.isPresent()) {
return marker.get();
}

var value = builder.value(valueParser.parse(s));
return value;
return builder.value(valueParser.parse(s));
};
}

Expand All @@ -331,11 +330,9 @@ public static <T> ValueParser<Optional<T>> optionalSingleton(Predicate<String> t
*/
public static ValueParser<Optional<Layer>> LAYER = s -> {
switch (s.toUpperCase()) {
case "1":
case "P":
case "1", "P":
return Optional.of(Layer.PRIMARY);
case "2":
case "S":
case "2", "S":
return Optional.of(Layer.SECONDARY);
case "V":
return Optional.of(Layer.VETERAN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static float ceil(float f) {
return (float) Math.ceil(f);
}

@SuppressWarnings("squid:S4274")
public static float clamp(float x, float min, float max) {
assert max >= min : "Maximum " + max + " was less than minimum " + min;
if (x < min)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package ca.bc.gov.nrs.vdyp.io.parse;

import static ca.bc.gov.nrs.vdyp.common.Utils.constMap;
import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.isMarker;
import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.isValue;
import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.notPresent;
import static ca.bc.gov.nrs.vdyp.test.VdypMatchers.present;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.Test;

public class ValueParserTest {
import ca.bc.gov.nrs.vdyp.common.Utils;
import ca.bc.gov.nrs.vdyp.model.Layer;
import ca.bc.gov.nrs.vdyp.test.VdypMatchers;

class ValueParserTest {

@Test
public void rangeParserTest() throws Exception {
void testRangeParser() throws Exception {
var exclusiveParser = ValueParser.range(ValueParser.INTEGER, 10, false, 20, false, "Test");

var result = exclusiveParser.parse("11");
Expand Down Expand Up @@ -53,4 +63,127 @@ public void rangeParserTest() throws Exception {

}

@Test
void testEnumParser() throws Exception {
var unit = ValueParser.enumParser(Layer.class);

assertThat(unit.parse("PRIMARY"), is(Layer.PRIMARY));

var ex = assertThrows(ValueParseException.class, () -> unit.parse("NOT_A_LAYER"));
assertThat(ex, hasProperty("message", is("\"NOT_A_LAYER\" is not a valid Layer")));
}

@Test
void testValidateRangeInclusive() throws Exception {
var unit = ValueParser.validateRangeInclusive(10f, 20f, "Test");

assertThat(unit.apply(10f), notPresent());
assertThat(unit.apply(20f), notPresent());
assertThat(unit.apply(11f), notPresent());
assertThat(unit.apply(19f), notPresent());
assertThat(unit.apply(9f), present(is("Test is expected to be between 10.0 and 20.0 but was 9.0")));
assertThat(unit.apply(21f), present(is("Test is expected to be between 10.0 and 20.0 but was 21.0")));

}

@Test
void testValidateRangeInclusiveBadRange() throws Exception {
assertThrows(IllegalArgumentException.class, () -> ValueParser.validateRangeInclusive(20f, 10f, "Test"));
}

@Test
void testPretestOptional() throws Exception {
var unit = ValueParser.pretestOptional(ValueParser.INTEGER, x -> !x.equals("IGNORE"));

assertThat(unit.parse("1"), present(is(1)));
assertThat(unit.parse("2"), present(is(2)));
assertThat(unit.parse("IGNORE"), notPresent());
assertThrows(ValueParseException.class, () -> unit.parse("DONT_IGNORE"));
}

@Test
void testPosttestOptional() throws Exception {
var unit = ValueParser.posttestOptional(ValueParser.INTEGER, x -> !x.equals(1));

assertThat(unit.parse("0"), present(is(0)));
assertThat(unit.parse("1"), notPresent());
assertThat(unit.parse("2"), present(is(2)));
assertThrows(ValueParseException.class, () -> unit.parse("DONT_IGNORE"));
}

@Test
void testValueOrMarker() throws Exception {
var unit = ValueParser.valueOrMarker(
ValueParser.INTEGER, ValueParser.pretestOptional(ValueParser.STRING, x -> x.equals("MARKER"))
);

assertThat(unit.parse("0"), isValue(is(0)));
assertThat(unit.parse("1"), isValue(is(1)));
assertThat(unit.parse("MARKER"), isMarker(is("MARKER")));
assertThrows(ValueParseException.class, () -> unit.parse("INVALID"));
}

@Test
void testOptionalSingleton() throws Exception {
var unit = ValueParser.optionalSingleton(x -> x.equals("PASS"), "X");

assertThat(unit.parse("FAIL"), notPresent());
assertThat(unit.parse("PASS"), present(is("X")));
}

@Test
void testLayer() throws Exception {
var unit = ValueParser.LAYER;

assertThat(unit.parse("1"), present(is(Layer.PRIMARY)));
assertThat(unit.parse("P"), present(is(Layer.PRIMARY)));

assertThat(unit.parse("2"), present(is(Layer.SECONDARY)));
assertThat(unit.parse("S"), present(is(Layer.SECONDARY)));

assertThat(unit.parse("V"), present(is(Layer.VETERAN)));

assertThat(unit.parse(""), notPresent());
assertThat(unit.parse(" "), notPresent());
assertThat(unit.parse("X"), notPresent());
}

@Test
void testToMap() throws Exception {
var map = Utils.<String, Integer>constMap(x -> {
x.put("K3", 42);
x.put("K4", 23);
});
var unit = ValueParser
.<String, Integer>toMap(ValueParser.list(ValueParser.INTEGER), map, "K1", "K2", "K3", "K4");

assertThat(unit.parse(" 2 3"), equalTo(constMap(x -> {
x.put("K1", 2);
x.put("K2", 3);
x.put("K3", 42);
x.put("K4", 23);
})));
assertThat(unit.parse(" 2 3 4"), equalTo(constMap(x -> {
x.put("K1", 2);
x.put("K2", 3);
x.put("K3", 4);
x.put("K4", 23);
})));
assertThat(unit.parse(" 2 3 4 5"), equalTo(constMap(x -> {
x.put("K1", 2);
x.put("K2", 3);
x.put("K3", 4);
x.put("K4", 5);
})));

assertThrows(ValueParseException.class, () -> unit.parse(" 2 "));

assertThrows(
IllegalArgumentException.class,
() -> ValueParser
.<String, Integer>toMap(ValueParser.list(ValueParser.INTEGER), map, "K1", "K3", "K2", "K4")
);

}

}

0 comments on commit ee2606f

Please sign in to comment.