diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index d417060ac7..4ab2f42ffe 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -6,10 +6,6 @@ on: - '**' workflow_dispatch: -concurrency: - group: it-${{ github.repository }} - cancel-in-progress: true - jobs: images: name: Build Docker Images @@ -72,14 +68,23 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 needs: images + strategy: + fail-fast: false + matrix: + device_id: [ "AHU-1", "AHU-22", "GAT-123" ] env: IMAGE_NAME: ${{ github.repository }} REF_NAME: ${{ github.ref_name }} + DEVICE_ID: ${{ matrix.device_id }} steps: - name: Setup Environment run: | + sudo apt-get install moreutils git clone https://github.com/faucetsdn/udmi_site_model.git ln -s udmi_site_model/ site_model + (cd site_model; git log -n 1) + jq ".device_id = \"$DEVICE_ID\"" site_model/cloud_iot_config.json | sponge site_model/cloud_iot_config.json + jq . site_model/cloud_iot_config.json docker network create udminet --subnet 192.168.99.0/24 - name: Start UDMIS container run: | @@ -116,13 +121,20 @@ jobs: docker logs pubber 2>&1 | fgrep "Connection complete" - name: Sequencer run run: | + SEQUENCER_TESTS="broken_config extra_config device_config_acked" + [[ $REF_NAME =~ test- ]] && SEQUENCER_TESTS=${REF_NAME#test-} docker run --net udminet --name sequencer -v $(realpath site_model):/root/site_model \ ghcr.io/$IMAGE_NAME:validator-$REF_NAME bin/sequencer site_model/cloud_iot_config.json \ - broken_config extra_config device_config_acked + $SEQUENCER_TESTS - name: Sequencer results run: | - cat site_model/out/devices/AHU-1/results.md - [[ $(cat site_model/out/devices/AHU-1/results.md | fgrep 'stable | pass' | wc -l) == 3 ]] + cat site_model/out/devices/$DEVICE_ID/results.md + if [[ $REF_NAME =~ test- ]]; then + SPECIFIC_TEST=${REF_NAME#test-} + more site_model/out/devices/$DEVICE_ID/tests/$SPECIFIC_TEST/* + else + [[ $(cat site_model/out/devices/$DEVICE_ID/results.md | fgrep 'stable | pass' | wc -l) == 3 ]] + fi - name: UDMIS logs if: ${{ !cancelled() }} run: docker logs udmis diff --git a/bin/clone_model b/bin/clone_model index a1d7be96ea..06772de076 100755 --- a/bin/clone_model +++ b/bin/clone_model @@ -5,7 +5,7 @@ mkdir -p $ROOT_DIR/sites cd $ROOT_DIR/sites MODEL_DIR=udmi_site_model -MODEL_VER=1.18 +MODEL_VER=1.19 TEST_SITE_GIT=https://github.com/faucetsdn/$MODEL_DIR.git MODEL_REPO=origin diff --git a/common/src/main/java/daq/pubber/ProtocolFamily.java b/common/src/main/java/daq/pubber/ProtocolFamily.java index 91e309c174..99049430f3 100644 --- a/common/src/main/java/daq/pubber/ProtocolFamily.java +++ b/common/src/main/java/daq/pubber/ProtocolFamily.java @@ -1,5 +1,8 @@ package daq.pubber; +import com.google.common.collect.ImmutableSet; +import java.util.Set; + public interface ProtocolFamily { String VENDOR = "vendor"; @@ -10,4 +13,6 @@ public interface ProtocolFamily { String BACNET = "bacnet"; String MODBUS = "modbus"; String INVALID = "invalid"; + + Set FAMILIES = ImmutableSet.of(VENDOR, IPV_4, IPV_6, ETHER, IOT, BACNET, MODBUS); } diff --git a/docs/specs/sequences/generated.md b/docs/specs/sequences/generated.md index 79214e9778..651b67f635 100644 --- a/docs/specs/sequences/generated.md +++ b/docs/specs/sequences/generated.md @@ -31,7 +31,9 @@ Some caveats: --> -* [bad_target_family](#bad_target_family-preview): Error handling for badly formed target address family +* [bad_point_ref](#bad_point_ref-preview): Error handling for badly formed gateway point ref +* [bad_target_address](#bad_target_address-preview): Error handling for badly formed gateway target address +* [bad_target_family](#bad_target_family-preview): Error handling for badly formed gateway target family * [broken_config](#broken_config-stable): Check that the device correctly handles a broken (non-json) config message. * [config_logging](#config_logging-stable): Check that the device publishes minimum required log entries when receiving config * [device_config_acked](#device_config_acked-stable): Check that the device MQTT-acknowledges a sent config. @@ -58,9 +60,21 @@ Some caveats: * [system_last_update](#system_last_update-stable): Check that last_update state is correctly set in response to a config update. * [valid_serial_no](#valid_serial_no-stable) +## bad_point_ref (PREVIEW) + +Error handling for badly formed gateway point ref + +1. Test skipped: Not a proxied device + +## bad_target_address (PREVIEW) + +Error handling for badly formed gateway target address + +1. Test skipped: Not a proxied device + ## bad_target_family (PREVIEW) -Error handling for badly formed target address family +Error handling for badly formed gateway target family 1. Test skipped: Not a proxied device diff --git a/etc/schema_itemized.out b/etc/schema_itemized.out index 3f39af2ab3..f2b28f00c4 100644 --- a/etc/schema_itemized.out +++ b/etc/schema_itemized.out @@ -47,3 +47,6 @@ 43 gateway_proxy_state 47 device_config_acked 48 bad_target_family +49 bad_target_address +50 bad_point_ref +54 bad_point_ref diff --git a/etc/schema_nostate.out b/etc/schema_nostate.out index bd74af945f..5111c2e974 100644 --- a/etc/schema_nostate.out +++ b/etc/schema_nostate.out @@ -1,2 +1,2 @@ -RESULT pass schemas device_state_stable BETA 5/5 Schema validation passed -RESULT pass schemas events_pointset_stable BETA 5/5 Schema validation passed +RESULT pass schemas device_state_stable STABLE 5/5 Schema validation passed +RESULT pass schemas events_pointset_stable STABLE 5/5 Schema validation passed diff --git a/etc/sequencer.out b/etc/sequencer.out index 64c921ee91..2ede3aadbb 100644 --- a/etc/sequencer.out +++ b/etc/sequencer.out @@ -16,6 +16,8 @@ RESULT pass enumeration multi_enumeration ALPHA 5/5 Sequence complete RESULT pass enumeration.families family_enumeration ALPHA 5/5 Sequence complete RESULT pass enumeration.features feature_enumeration PREVIEW 5/5 Sequence complete RESULT pass enumeration.pointset pointset_enumeration ALPHA 5/5 Sequence complete +RESULT skip gateway bad_point_ref PREVIEW 0/0 Not a proxied device +RESULT skip gateway bad_target_address PREVIEW 0/0 Not a proxied device RESULT skip gateway bad_target_family PREVIEW 0/0 Not a proxied device RESULT skip gateway gateway_attach_handling ALPHA 0/0 Not a gateway RESULT skip gateway gateway_proxy_events BETA 0/0 Not a gateway diff --git a/etc/sequencer_nostate.out b/etc/sequencer_nostate.out index 87a15f981a..930f8ac3bb 100644 --- a/etc/sequencer_nostate.out +++ b/etc/sequencer_nostate.out @@ -6,6 +6,8 @@ RESULT skip endpoint.config endpoint_failure_and_restart PREVIEW 0/0 State testi RESULT skip endpoint.config endpoint_redirect_and_restart PREVIEW 0/0 State testing disabled RESULT skip enumeration empty_enumeration PREVIEW 0/0 State testing disabled RESULT skip enumeration.features feature_enumeration PREVIEW 0/0 State testing disabled +RESULT skip gateway bad_point_ref PREVIEW 0/0 Not a proxied device +RESULT skip gateway bad_target_address PREVIEW 0/0 Not a proxied device RESULT skip gateway bad_target_family PREVIEW 0/0 Not a proxied device RESULT skip gateway gateway_proxy_events BETA 0/0 Not a gateway RESULT skip gateway gateway_proxy_state PREVIEW 0/0 Not a gateway diff --git a/etc/test_itemized.in b/etc/test_itemized.in index b9326e1182..00f0251d27 100644 --- a/etc/test_itemized.in +++ b/etc/test_itemized.in @@ -46,3 +46,9 @@ TEST gateway_proxy_state noState WITH AHU-22 TEST device_config_acked TEST bad_target_family +TEST bad_target_address +TEST bad_point_ref + +# Test a proxy device with a different configuration +WITH SNS-4 +TEST bad_point_ref diff --git a/etc/test_itemized.out b/etc/test_itemized.out index 30086f235d..c0ffcf7904 100644 --- a/etc/test_itemized.out +++ b/etc/test_itemized.out @@ -44,3 +44,6 @@ 43 RESULT pass gateway gateway_proxy_state PREVIEW 5/5 Sequence complete 47 RESULT skip system device_config_acked STABLE 0/0 No config check for proxy device 48 RESULT pass gateway bad_target_family PREVIEW 5/5 Sequence complete +49 RESULT pass gateway bad_target_address PREVIEW 5/5 Sequence complete +50 RESULT pass gateway bad_point_ref PREVIEW 5/5 Sequence complete +54 RESULT skip gateway bad_point_ref PREVIEW 0/0 No testing target defined for 'tweaked_ref' diff --git a/pubber/src/main/java/daq/pubber/BasicPoint.java b/pubber/src/main/java/daq/pubber/BasicPoint.java index efba997c86..0b2124ec91 100644 --- a/pubber/src/main/java/daq/pubber/BasicPoint.java +++ b/pubber/src/main/java/daq/pubber/BasicPoint.java @@ -1,12 +1,16 @@ package daq.pubber; +import static com.google.udmi.util.GeneralUtils.deepCopy; import static com.google.udmi.util.GeneralUtils.getNow; +import static com.google.udmi.util.GeneralUtils.isTrue; +import java.util.Objects; import udmi.schema.Category; import udmi.schema.Entry; import udmi.schema.PointDiscovery; import udmi.schema.PointPointsetConfig; import udmi.schema.PointPointsetEvents; +import udmi.schema.PointPointsetModel; import udmi.schema.PointPointsetState; import udmi.schema.PointPointsetState.Value_state; @@ -19,21 +23,19 @@ public abstract class BasicPoint implements AbstractPoint { protected final PointPointsetEvents data = new PointPointsetEvents(); private final PointPointsetState state = new PointPointsetState(); private final boolean writable; + private final String pointRef; protected boolean written; private boolean dirty; /** * Construct a maybe writable point. - * - * @param name Point name - * @param writable True if writable - * @param units Units for the point */ - public BasicPoint(String name, boolean writable, String units) { + public BasicPoint(String name, PointPointsetModel pointModel) { this.name = name; - this.writable = writable; - state.units = units; + writable = isTrue(pointModel.writable); + state.units = pointModel.units; dirty = true; + pointRef = pointModel.ref; } protected abstract Object getValue(); @@ -72,14 +74,29 @@ public PointPointsetEvents getData() { * @param config Configuration to set */ public void setConfig(PointPointsetConfig config) { - Value_state previous = state.value_state; + Value_state previousValueState = state.value_state; + Entry previousStatus = deepCopy(state.status); + updateStateConfig(config); + dirty = dirty + || state.value_state != previousValueState + || !Objects.equals(state.status, previousStatus); + } + + /** + * Update the state of this point based off of a new config. + */ + public void updateStateConfig(PointPointsetConfig config) { state.status = null; + if (config != null && !Objects.equals(pointRef, config.ref)) { + state.status = createEntryFrom(Category.POINTSET_POINT_FAILURE, "Invalid point ref"); + return; + } + if (config == null || config.set_value == null) { written = false; state.value_state = null; updateData(); - dirty = state.value_state != previous; return; } @@ -88,20 +105,17 @@ public void setConfig(PointPointsetConfig config) { state.status = createEntryFrom(Category.POINTSET_POINT_INVALID, "Written value is not valid"); state.value_state = Value_state.INVALID; - dirty = state.value_state != previous; return; } } catch (Exception ex) { state.status = createEntryFrom(Category.POINTSET_POINT_FAILURE, ex.getMessage()); state.value_state = Value_state.FAILURE; - dirty = state.value_state != previous; return; } if (!writable) { state.status = createEntryFrom(Category.POINTSET_POINT_FAILURE, "Point is not writable"); state.value_state = Value_state.FAILURE; - dirty = state.value_state != previous; return; } @@ -113,7 +127,6 @@ public void setConfig(PointPointsetConfig config) { state.status = createEntryFrom(Category.POINTSET_POINT_FAILURE, ex.getMessage()); state.value_state = Value_state.FAILURE; } - dirty = state.value_state != previous; } @Override diff --git a/pubber/src/main/java/daq/pubber/GatewayManager.java b/pubber/src/main/java/daq/pubber/GatewayManager.java index 46c65d8cc2..1fdd32f6f6 100644 --- a/pubber/src/main/java/daq/pubber/GatewayManager.java +++ b/pubber/src/main/java/daq/pubber/GatewayManager.java @@ -1,7 +1,6 @@ package daq.pubber; import static com.google.udmi.util.GeneralUtils.catchToNull; -import static com.google.udmi.util.GeneralUtils.deepCopy; import static com.google.udmi.util.GeneralUtils.getNow; import static com.google.udmi.util.GeneralUtils.ifNotNullGet; import static com.google.udmi.util.GeneralUtils.ifNotNullThen; @@ -11,14 +10,13 @@ import static com.google.udmi.util.GeneralUtils.isTrue; import static java.lang.String.format; import static java.util.Optional.ofNullable; +import static java.util.function.Predicate.not; import static udmi.schema.Category.GATEWAY_PROXY_TARGET; import com.google.udmi.util.SiteModel; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import udmi.schema.Config; import udmi.schema.Entry; import udmi.schema.GatewayConfig; @@ -51,16 +49,12 @@ private Map createProxyDevices(List proxyIds) { } Map devices = new HashMap<>(); - if (!proxyIds.isEmpty()) { - String firstId = proxyIds.stream().sorted().findFirst().orElseThrow(); - String noProxyId = ifTrueGet(isTrue(options.noProxy), () -> firstId); - ifNotNullThen(noProxyId, id -> warn(format("Not proxying device %s", noProxyId))); - proxyIds.forEach(id -> { - if (!id.equals(noProxyId)) { - devices.put(id, new ProxyDevice(host, id, config)); - } - }); - } + + String firstId = proxyIds.stream().sorted().findFirst().orElse(null); + String noProxyId = ifTrueGet(isTrue(options.noProxy), () -> firstId); + ifNotNullThen(noProxyId, id -> warn(format("Not proxying device %s", noProxyId))); + proxyIds.stream().filter(not(id -> id.equals(noProxyId))) + .forEach(id -> devices.put(id, new ProxyDevice(host, id, config))); ifTrueThen(options.extraDevice, () -> devices.put(EXTRA_PROXY_DEVICE, makeExtraDevice())); @@ -92,7 +86,9 @@ ProxyDevice makeExtraDevice() { } /** - * Update gateway operation based off of a gateway configuration block. + * Update gateway operation based off of a gateway configuration block. This happens in two + * slightly different forms, one for the gateway proper (primarily indicating what devices + * should be proxy targets), and the other for the proxy devices themselves. */ public void updateConfig(GatewayConfig gateway) { if (gateway == null) { @@ -107,7 +103,10 @@ public void updateConfig(GatewayConfig gateway) { if (gateway.proxy_ids == null || gateway.target != null) { try { - String family = validateGatewayFamily(catchToNull(() -> gateway.target.family)); + String addr = catchToNull(() -> gateway.target.addr); + String family = ofNullable(catchToNull(() -> gateway.target.family)) + .orElse(ProtocolFamily.VENDOR); + validateGatewayFamily(family, addr); setGatewayStatus(GATEWAY_PROXY_TARGET, Level.DEBUG, "gateway target family " + family); } catch (Exception e) { setGatewayStatus(GATEWAY_PROXY_TARGET, Level.ERROR, e.getMessage()); @@ -129,14 +128,17 @@ private void updateState() { updateState(ofNullable((Object) gatewayState).orElse(GatewayState.class)); } - private String validateGatewayFamily(String family) { - if (family == null) { - return null; + private void validateGatewayFamily(String family, String addr) { + if (!ProtocolFamily.FAMILIES.contains(family)) { + throw new IllegalArgumentException("Unrecognized address family " + family); + } + + String expectedAddr = catchToNull(() -> metadata.localnet.families.get(family).addr); + + if (expectedAddr != null && !expectedAddr.equals(addr)) { + throw new IllegalStateException( + format("Family address was %s, expected %s", addr, expectedAddr)); } - debug("Validating gateway family " + family); - Objects.requireNonNull(catchToNull(() -> metadata.localnet.families.get(family).addr), - format("Address family %s addr is null or undefined", family)); - return family; } private void configExtraDevice() { diff --git a/pubber/src/main/java/daq/pubber/ManagerBase.java b/pubber/src/main/java/daq/pubber/ManagerBase.java index a4b35ec273..765338da00 100644 --- a/pubber/src/main/java/daq/pubber/ManagerBase.java +++ b/pubber/src/main/java/daq/pubber/ManagerBase.java @@ -154,7 +154,7 @@ protected synchronized void startPeriodicSend() { warn(format("Starting %s %s sender with delay %ds", deviceId, this.getClass().getSimpleName(), sec)); if (sec != 0) { - periodicUpdate(); // To this now to synchronously raise any obvious exceptions. + periodicUpdate(); // Do this now to synchronously raise any obvious exceptions. periodicSender = schedulePeriodic(sec, this::periodicUpdate); } } diff --git a/pubber/src/main/java/daq/pubber/PointsetManager.java b/pubber/src/main/java/daq/pubber/PointsetManager.java index 63d2d63e2e..b454f460b1 100644 --- a/pubber/src/main/java/daq/pubber/PointsetManager.java +++ b/pubber/src/main/java/daq/pubber/PointsetManager.java @@ -42,7 +42,6 @@ public class PointsetManager extends ManagerBase { private static final Set BOOLEAN_UNITS = ImmutableSet.of("No-units"); - private static final double DEFAULT_BASELINE_VALUE = 50; private static final Map DEFAULT_POINTS = ImmutableMap.of( "recalcitrant_angle", makePointPointsetModel(true, 50, 50, "Celsius"), @@ -85,31 +84,13 @@ private static PointPointsetEvents extraPointsetEvent() { } private AbstractPoint makePoint(String name, PointPointsetModel point) { - boolean writable = point.writable != null && point.writable; if (BOOLEAN_UNITS.contains(point.units)) { - return new RandomBoolean(name, writable); + return new RandomBoolean(name, point); } else { - double baselineValue = convertValue(point.baseline_value, DEFAULT_BASELINE_VALUE); - double baselineTolerance = convertValue(point.baseline_tolerance, baselineValue); - double min = baselineValue - baselineTolerance; - double max = baselineValue + baselineTolerance; - return new RandomPoint(name, writable, min, max, point.units); + return new RandomPoint(name, point); } } - private double convertValue(Object baselineValue, double defaultBaselineValue) { - if (baselineValue == null) { - return defaultBaselineValue; - } - if (baselineValue instanceof Double) { - return (double) baselineValue; - } - if (baselineValue instanceof Integer) { - return (double) (int) baselineValue; - } - throw new RuntimeException("Unknown value type " + baselineValue.getClass()); - } - public void setExtraField(String extraField) { ifNotNullThen(extraField, field -> pointsetEvent.extraField = field); } diff --git a/pubber/src/main/java/daq/pubber/RandomBoolean.java b/pubber/src/main/java/daq/pubber/RandomBoolean.java index 8006f760c5..8f8c0daf38 100644 --- a/pubber/src/main/java/daq/pubber/RandomBoolean.java +++ b/pubber/src/main/java/daq/pubber/RandomBoolean.java @@ -1,14 +1,15 @@ package daq.pubber; import udmi.schema.PointDiscovery; +import udmi.schema.PointPointsetModel; /** * Represents a random boolean point. */ public class RandomBoolean extends BasicPoint implements AbstractPoint { - public RandomBoolean(String name, boolean writable) { - super(name, writable, null); + public RandomBoolean(String name, PointPointsetModel pointModel) { + super(name, pointModel); } @Override diff --git a/pubber/src/main/java/daq/pubber/RandomPoint.java b/pubber/src/main/java/daq/pubber/RandomPoint.java index 054b5c5794..81a07d9a77 100644 --- a/pubber/src/main/java/daq/pubber/RandomPoint.java +++ b/pubber/src/main/java/daq/pubber/RandomPoint.java @@ -1,32 +1,41 @@ package daq.pubber; import udmi.schema.PointDiscovery; +import udmi.schema.PointPointsetModel; /** * Represents a randomly generated numerical point. */ public class RandomPoint extends BasicPoint implements AbstractPoint { - private final String name; + private static final double DEFAULT_BASELINE_VALUE = 50; private final double min; private final double max; private final String units; /** * Creates a random point generator for data simulation. - * - * @param name point name - * @param writable indicates if point is writable - * @param min minimum value for generated point - * @param max maximum value for generated point - * @param units units of generated point */ - public RandomPoint(String name, boolean writable, double min, double max, String units) { - super(name, writable, units); - this.name = name; - this.min = min; - this.max = max; - this.units = units; + public RandomPoint(String name, PointPointsetModel pointModel) { + super(name, pointModel); + double baselineValue = convertValue(pointModel.baseline_value, DEFAULT_BASELINE_VALUE); + double baselineTolerance = convertValue(pointModel.baseline_tolerance, baselineValue); + this.min = baselineValue - baselineTolerance; + this.max = baselineValue + baselineTolerance; + this.units = pointModel.units; + } + + private double convertValue(Object baselineValue, double defaultBaselineValue) { + if (baselineValue == null) { + return defaultBaselineValue; + } + if (baselineValue instanceof Double) { + return (double) baselineValue; + } + if (baselineValue instanceof Integer) { + return (double) (int) baselineValue; + } + throw new RuntimeException("Unknown value type " + baselineValue.getClass()); } @Override diff --git a/validator/sequences/bad_point_ref/sequence.md b/validator/sequences/bad_point_ref/sequence.md new file mode 100644 index 0000000000..29bc68b446 --- /dev/null +++ b/validator/sequences/bad_point_ref/sequence.md @@ -0,0 +1,6 @@ + +## bad_point_ref (PREVIEW) + +Error handling for badly formed gateway point ref + +1. Test skipped: Not a proxied device diff --git a/validator/sequences/bad_point_ref/sequencer.log b/validator/sequences/bad_point_ref/sequencer.log new file mode 100644 index 0000000000..bfe7cda1c8 --- /dev/null +++ b/validator/sequences/bad_point_ref/sequencer.log @@ -0,0 +1,29 @@ +2024-08-26T15:14:30Z NOTICE starting test bad_point_ref ################################ +2024-08-26T15:14:30Z DEBUG Suppressing exception: java.lang.NullPointerException: Cannot read field "gateway_id" because "com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.deviceMetadata.gateway" is null +2024-08-26T15:14:30Z DEBUG stage done initialize at 0s +2024-08-26T15:14:30Z DEBUG exception message: Not a proxied device +2024-08-26T15:14:30Z TRACE ending stack trace: org.junit.AssumptionViolatedException: Not a proxied device +2024-08-26T15:14:30Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.skipTest(SequenceBase.java:2222) +2024-08-26T15:14:30Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.lambda$ifTrueSkipTest$88(SequenceBase.java:2226) +2024-08-26T15:14:30Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:372) +2024-08-26T15:14:30Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:367) +2024-08-26T15:14:30Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.ifTrueSkipTest(SequenceBase.java:2226) +2024-08-26T15:14:30Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.setUp(ProxiedSequences.java:33) +2024-08-26T15:14:30Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) +2024-08-26T15:14:30Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) +2024-08-26T15:14:30Z TRACE ending stack trace: at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) +2024-08-26T15:14:30Z TRACE ending stack trace: at java.base/java.lang.reflect.Method.invoke(Method.java:569) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299) +2024-08-26T15:14:30Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293) +2024-08-26T15:14:30Z TRACE ending stack trace: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) +2024-08-26T15:14:30Z TRACE ending stack trace: at java.base/java.lang.Thread.run(Thread.java:840) +2024-08-26T15:14:30Z DEBUG Removing implicit system capability LAST_CONFIG +2024-08-26T15:14:30Z NOTICE RESULT skip gateway bad_point_ref PREVIEW 0/0 Not a proxied device +2024-08-26T15:14:30Z WARNING Not a proxied device +2024-08-26T15:14:30Z NOTICE ending test bad_point_ref after 0s ################################ diff --git a/validator/sequences/bad_point_ref/system.log b/validator/sequences/bad_point_ref/system.log new file mode 100644 index 0000000000..09658ed1bd --- /dev/null +++ b/validator/sequences/bad_point_ref/system.log @@ -0,0 +1 @@ +2024-08-26T15:14:30Z WARNING Not a proxied device diff --git a/validator/sequences/bad_target_address/sequence.md b/validator/sequences/bad_target_address/sequence.md new file mode 100644 index 0000000000..7a78c1b64c --- /dev/null +++ b/validator/sequences/bad_target_address/sequence.md @@ -0,0 +1,6 @@ + +## bad_target_address (PREVIEW) + +Error handling for badly formed gateway target address + +1. Test skipped: Not a proxied device diff --git a/validator/sequences/bad_target_address/sequencer.log b/validator/sequences/bad_target_address/sequencer.log new file mode 100644 index 0000000000..8a92db3e5b --- /dev/null +++ b/validator/sequences/bad_target_address/sequencer.log @@ -0,0 +1,29 @@ +2024-08-26T15:18:01Z NOTICE starting test bad_target_address ################################ +2024-08-26T15:18:01Z DEBUG Suppressing exception: java.lang.NullPointerException: Cannot read field "gateway_id" because "com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.deviceMetadata.gateway" is null +2024-08-26T15:18:01Z DEBUG stage done initialize at 0s +2024-08-26T15:18:01Z DEBUG exception message: Not a proxied device +2024-08-26T15:18:01Z TRACE ending stack trace: org.junit.AssumptionViolatedException: Not a proxied device +2024-08-26T15:18:01Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.skipTest(SequenceBase.java:2222) +2024-08-26T15:18:01Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.lambda$ifTrueSkipTest$88(SequenceBase.java:2226) +2024-08-26T15:18:01Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:372) +2024-08-26T15:18:01Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:367) +2024-08-26T15:18:01Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.ifTrueSkipTest(SequenceBase.java:2226) +2024-08-26T15:18:01Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.setUp(ProxiedSequences.java:33) +2024-08-26T15:18:01Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) +2024-08-26T15:18:01Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) +2024-08-26T15:18:01Z TRACE ending stack trace: at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) +2024-08-26T15:18:01Z TRACE ending stack trace: at java.base/java.lang.reflect.Method.invoke(Method.java:569) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299) +2024-08-26T15:18:01Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293) +2024-08-26T15:18:01Z TRACE ending stack trace: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) +2024-08-26T15:18:01Z TRACE ending stack trace: at java.base/java.lang.Thread.run(Thread.java:840) +2024-08-26T15:18:01Z DEBUG Removing implicit system capability LAST_CONFIG +2024-08-26T15:18:01Z NOTICE RESULT skip gateway bad_target_address PREVIEW 0/0 Not a proxied device +2024-08-26T15:18:01Z WARNING Not a proxied device +2024-08-26T15:18:01Z NOTICE ending test bad_target_address after 0s ################################ diff --git a/validator/sequences/bad_target_address/system.log b/validator/sequences/bad_target_address/system.log new file mode 100644 index 0000000000..2b07a651d6 --- /dev/null +++ b/validator/sequences/bad_target_address/system.log @@ -0,0 +1 @@ +2024-08-26T15:18:01Z WARNING Not a proxied device diff --git a/validator/sequences/bad_target_family/sequence.md b/validator/sequences/bad_target_family/sequence.md index 2c2be0fcce..2ae46137c4 100644 --- a/validator/sequences/bad_target_family/sequence.md +++ b/validator/sequences/bad_target_family/sequence.md @@ -1,6 +1,6 @@ ## bad_target_family (PREVIEW) -Error handling for badly formed target address family +Error handling for badly formed gateway target family 1. Test skipped: Not a proxied device diff --git a/validator/sequences/bad_target_family/sequencer.log b/validator/sequences/bad_target_family/sequencer.log index 08f26336eb..f00f39f20c 100644 --- a/validator/sequences/bad_target_family/sequencer.log +++ b/validator/sequences/bad_target_family/sequencer.log @@ -1,29 +1,29 @@ -2024-03-10T18:08:42Z NOTICE starting test bad_target_family ################################ -2024-03-10T18:08:42Z DEBUG Suppressing exception: java.lang.NullPointerException: Cannot read field "gateway_id" because "com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.deviceMetadata.gateway" is null -2024-03-10T18:08:42Z DEBUG stage done initialize at 0s -2024-03-10T18:08:42Z DEBUG exception message: Not a proxied device -2024-03-10T18:08:42Z TRACE ending stack trace: org.junit.AssumptionViolatedException: Not a proxied device -2024-03-10T18:08:42Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.skipTest(SequenceBase.java:2064) -2024-03-10T18:08:42Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.lambda$ifTrueSkipTest$73(SequenceBase.java:2068) -2024-03-10T18:08:42Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:309) -2024-03-10T18:08:42Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:304) -2024-03-10T18:08:42Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.ifTrueSkipTest(SequenceBase.java:2068) -2024-03-10T18:08:42Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.setUp(ProxiedSequences.java:27) -2024-03-10T18:08:42Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) -2024-03-10T18:08:42Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) -2024-03-10T18:08:42Z TRACE ending stack trace: at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) -2024-03-10T18:08:42Z TRACE ending stack trace: at java.base/java.lang.reflect.Method.invoke(Method.java:568) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299) -2024-03-10T18:08:42Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293) -2024-03-10T18:08:42Z TRACE ending stack trace: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) -2024-03-10T18:08:42Z TRACE ending stack trace: at java.base/java.lang.Thread.run(Thread.java:840) -2024-03-10T18:08:42Z DEBUG Removing implicit system capability LAST_CONFIG -2024-03-10T18:08:42Z NOTICE RESULT skip gateway bad_target_family PREVIEW 0/0 Not a proxied device -2024-03-10T18:08:42Z WARNING Not a proxied device -2024-03-10T18:08:42Z NOTICE ending test bad_target_family after 0s ################################ +2024-08-26T15:15:06Z NOTICE starting test bad_target_family ################################ +2024-08-26T15:15:06Z DEBUG Suppressing exception: java.lang.NullPointerException: Cannot read field "gateway_id" because "com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.deviceMetadata.gateway" is null +2024-08-26T15:15:06Z DEBUG stage done initialize at 0s +2024-08-26T15:15:06Z DEBUG exception message: Not a proxied device +2024-08-26T15:15:06Z TRACE ending stack trace: org.junit.AssumptionViolatedException: Not a proxied device +2024-08-26T15:15:06Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.skipTest(SequenceBase.java:2222) +2024-08-26T15:15:06Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.lambda$ifTrueSkipTest$88(SequenceBase.java:2226) +2024-08-26T15:15:06Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:372) +2024-08-26T15:15:06Z TRACE ending stack trace: at com.google.udmi.util.GeneralUtils.ifTrueThen(GeneralUtils.java:367) +2024-08-26T15:15:06Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.SequenceBase.ifTrueSkipTest(SequenceBase.java:2226) +2024-08-26T15:15:06Z TRACE ending stack trace: at com.google.daq.mqtt.sequencer.sequences.ProxiedSequences.setUp(ProxiedSequences.java:33) +2024-08-26T15:15:06Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) +2024-08-26T15:15:06Z TRACE ending stack trace: at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) +2024-08-26T15:15:06Z TRACE ending stack trace: at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) +2024-08-26T15:15:06Z TRACE ending stack trace: at java.base/java.lang.reflect.Method.invoke(Method.java:569) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299) +2024-08-26T15:15:06Z TRACE ending stack trace: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293) +2024-08-26T15:15:06Z TRACE ending stack trace: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) +2024-08-26T15:15:06Z TRACE ending stack trace: at java.base/java.lang.Thread.run(Thread.java:840) +2024-08-26T15:15:06Z DEBUG Removing implicit system capability LAST_CONFIG +2024-08-26T15:15:06Z NOTICE RESULT skip gateway bad_target_family PREVIEW 0/0 Not a proxied device +2024-08-26T15:15:06Z WARNING Not a proxied device +2024-08-26T15:15:06Z NOTICE ending test bad_target_family after 0s ################################ diff --git a/validator/sequences/bad_target_family/system.log b/validator/sequences/bad_target_family/system.log index dfca3a5aaf..53dc737be9 100644 --- a/validator/sequences/bad_target_family/system.log +++ b/validator/sequences/bad_target_family/system.log @@ -1 +1 @@ -2024-03-10T18:08:42Z WARNING Not a proxied device +2024-08-26T15:15:06Z WARNING Not a proxied device diff --git a/validator/src/main/java/com/google/daq/mqtt/sequencer/PointsetBase.java b/validator/src/main/java/com/google/daq/mqtt/sequencer/PointsetBase.java index 1e15381d6d..ecb33d563c 100644 --- a/validator/src/main/java/com/google/daq/mqtt/sequencer/PointsetBase.java +++ b/validator/src/main/java/com/google/daq/mqtt/sequencer/PointsetBase.java @@ -1,11 +1,11 @@ package com.google.daq.mqtt.sequencer; -import com.google.daq.mqtt.sequencer.sequences.WritebackSequences; import java.util.HashMap; import java.util.Optional; import org.junit.AssumptionViolatedException; import org.junit.Before; import udmi.schema.PointPointsetConfig; +import udmi.schema.PointPointsetModel; import udmi.schema.PointsetConfig; import udmi.schema.TargetTestingModel; @@ -14,6 +14,11 @@ */ public abstract class PointsetBase extends SequenceBase { + public static final String INVALID_STATE = "invalid"; + public static final String FAILURE_STATE = "failure"; + public static final String APPLIED_STATE = "applied"; + public static final String TWEAKED_REF = "tweaked_ref"; + @Override public void setUp() { ifTrueSkipTest(catchToTrue(() -> deviceMetadata.pointset == null), "Does not support pointset"); @@ -29,9 +34,9 @@ public void makePoints() { deviceConfig.pointset.points = Optional.ofNullable(deviceConfig.pointset.points) .orElse(new HashMap<>()); try { - ensurePointConfig(WritebackSequences.INVALID_STATE); - ensurePointConfig(WritebackSequences.FAILURE_STATE); - ensurePointConfig(WritebackSequences.APPLIED_STATE); + ensurePointConfig(INVALID_STATE); + ensurePointConfig(FAILURE_STATE); + ensurePointConfig(APPLIED_STATE); } catch (AssumptionViolatedException skipTest) { info("Not setting config points: " + skipTest.getMessage()); } @@ -49,14 +54,11 @@ private PointPointsetConfig makePointsetConfig(String pointName) { protected TargetTestingModel getTarget(String target) { TargetTestingModel testingMetadata = ifNullSkipTest( catchToNull(() -> deviceMetadata.testing.targets.get(target)), - "no testing target defined for '" + target + "'"); - if (deviceMetadata.pointset == null || deviceMetadata.pointset.points == null) { - info("No metadata pointset points defined, I hope you know what you're doing"); - } else if (!deviceMetadata.pointset.points.containsKey(testingMetadata.target_point)) { - throw new RuntimeException( - String.format("Testing target %s point '%s' not defined in pointset metadata", - target, testingMetadata.target_point)); - } + "No testing target defined for '" + target + "'"); + PointPointsetModel pointPointsetModel = catchToNull( + () -> deviceMetadata.pointset.points.get(testingMetadata.target_point)); + ifNullSkipTest(pointPointsetModel, + "No pointset model for target point " + testingMetadata.target_point); return testingMetadata; } } diff --git a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ProxiedSequences.java b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ProxiedSequences.java index be1bcc730c..0eb14d9979 100644 --- a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ProxiedSequences.java +++ b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ProxiedSequences.java @@ -1,21 +1,25 @@ package com.google.daq.mqtt.sequencer.sequences; +import static com.google.daq.mqtt.sequencer.semantic.SemanticValue.describe; import static com.google.daq.mqtt.util.TimePeriodConstants.TWO_MINUTES_MS; import static com.google.udmi.util.GeneralUtils.catchToElse; import static com.google.udmi.util.GeneralUtils.deepCopy; import static com.google.udmi.util.GeneralUtils.ifNullThen; +import static java.lang.String.format; import static udmi.schema.Category.GATEWAY_PROXY_TARGET; +import static udmi.schema.Category.POINTSET_POINT_FAILURE; import com.google.daq.mqtt.sequencer.Feature; import com.google.daq.mqtt.sequencer.PointsetBase; import com.google.daq.mqtt.sequencer.Summary; -import daq.pubber.ProtocolFamily; import org.junit.Test; import udmi.schema.Bucket; +import udmi.schema.Entry; import udmi.schema.FamilyLocalnetModel; import udmi.schema.FeatureDiscovery.FeatureStage; import udmi.schema.GatewayConfig; import udmi.schema.Level; +import udmi.schema.PointPointsetConfig; ; @@ -32,35 +36,81 @@ public void setUp() { } @Feature(stage = FeatureStage.PREVIEW, bucket = Bucket.GATEWAY) - @Summary("Error handling for badly formed target address family") + @Summary("Error handling for badly formed gateway target family") @Test(timeout = TWO_MINUTES_MS) public void bad_target_family() { - cleanStatusCheck(); + cleanStatusCheck(null); GatewayConfig gatewayConfig = deviceConfig.gateway; final FamilyLocalnetModel savedTarget = deepCopy(gatewayConfig.target); ifNullThen(gatewayConfig.target, () -> gatewayConfig.target = new FamilyLocalnetModel()); - gatewayConfig.target.family = ProtocolFamily.INVALID; - untilTrue("gateway status has target error", this::hasTargetError); - gatewayConfig.target = savedTarget; - untilFalse("restored original target config", this::hasGatewayStatus); + gatewayConfig.target.family = getRandomCode("family"); + untilTrue("gateway status has target family error", this::hasGatewayStatusError); + gatewayConfig.target.family = describe("original family", savedTarget.family); + untilFalse("gateway status has no error", this::hasGatewayStatusDirty); } - private void cleanStatusCheck() { - checkNotThat("gateway state with significant status", this::hasGatewayStatus); + @Feature(stage = FeatureStage.PREVIEW, bucket = Bucket.GATEWAY) + @Summary("Error handling for badly formed gateway target address") + @Test(timeout = TWO_MINUTES_MS) + public void bad_target_address() { + cleanStatusCheck(null); + GatewayConfig gatewayConfig = deviceConfig.gateway; + final FamilyLocalnetModel savedTarget = deepCopy(gatewayConfig.target); + ifNullThen(gatewayConfig.target, () -> gatewayConfig.target = new FamilyLocalnetModel()); + gatewayConfig.target.addr = getRandomCode("addr"); + untilTrue("gateway status has target addr error", this::hasGatewayStatusError); + gatewayConfig.target.addr = describe("original addr", savedTarget.addr); + untilFalse("gateway status has no error", this::hasGatewayStatusDirty); } - private boolean hasGatewayStatus() { + @Feature(stage = FeatureStage.PREVIEW, bucket = Bucket.GATEWAY) + @Summary("Error handling for badly formed gateway point ref") + @Test(timeout = TWO_MINUTES_MS) + public void bad_point_ref() { + String targetPoint = getTarget(TWEAKED_REF).target_point; + cleanStatusCheck(targetPoint); + PointPointsetConfig pointPointsetConfig = deviceConfig.pointset.points.get(targetPoint); + String savedRef = pointPointsetConfig.ref; + pointPointsetConfig.ref = getRandomCode("ref"); + untilTrue("point status has target error", this::hasPointStatusError); + pointPointsetConfig.ref = describe("original ref", savedRef); + untilFalse("no more pointset error", this::hasPointStatusDirty); + } + + private void cleanStatusCheck(String targetPoint) { + checkNotThat("gateway state with significant status", this::hasGatewayStatusDirty); + if (targetPoint != null) { + checkNotThat("pointset state with significant status", this::hasPointStatusDirty); + } + } + + private boolean hasGatewayStatusDirty() { Integer level = catchToElse(() -> deviceState.gateway.status.level, Level.INFO.value()); return level > Level.INFO.value(); } - private boolean hasTargetError() { - return hasGatewayStatus() + private boolean hasGatewayStatusError() { + return hasGatewayStatusDirty() && GATEWAY_PROXY_TARGET.equals(deviceState.gateway.status.category) && Level.ERROR == Level.fromValue(deviceState.gateway.status.level); } - private String getRandomFamily() { - return "family-" + String.format("%04x", (int) Math.floor(Math.random() * 0x10000)); + private boolean hasPointStatusDirty() { + String targetPoint = getTarget(TWEAKED_REF).target_point; + Entry status = deviceState.pointset.points.get(targetPoint).status; + return catchToElse(() -> status.level, Level.INFO.value()) > Level.INFO.value(); + } + + private boolean hasPointStatusError() { + String targetPoint = getTarget(TWEAKED_REF).target_point; + Entry status = deviceState.pointset.points.get(targetPoint).status; + return hasPointStatusDirty() + && POINTSET_POINT_FAILURE.equals(status.category) + && Level.ERROR == Level.fromValue(status.level); + } + + private String getRandomCode(String prefix) { + return describe("random " + prefix, + format("%s-%04x", prefix, (int) Math.floor(Math.random() * 0x10000))); } } diff --git a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/WritebackSequences.java b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/WritebackSequences.java index 48eb5c3646..3b39c2c5aa 100644 --- a/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/WritebackSequences.java +++ b/validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/WritebackSequences.java @@ -21,9 +21,6 @@ */ public class WritebackSequences extends PointsetBase { - public static final String INVALID_STATE = "invalid"; - public static final String FAILURE_STATE = "failure"; - public static final String APPLIED_STATE = "applied"; public static final String DEFAULT_STATE = null; private Object lastPresentValue;