Skip to content

Commit 994b89f

Browse files
committed
Fix logordering race condition for broken_config test (#627)
1 parent dc3dc17 commit 994b89f

File tree

9 files changed

+96
-9
lines changed

9 files changed

+96
-9
lines changed

.gencode_hash.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ e693079943921c88e24140521637c58bc9aadfb9aee96dfba414bbaa7be958d0 gencode/docs/c
44
20fc22e10cf8ac92d21e1fb5b59052de11ec5d842d36615ac51815dc12588ed9 gencode/docs/config_mapping.html
55
cc4bb19794042f88f3a72b197b4d21736e5cebf6ec47ffac560430e9f580181f gencode/docs/configuration_endpoint.html
66
4da8ddd26aed7428171e1cbc6d134b37e30a958d09ce0f255bbb22b130d26f77 gencode/docs/configuration_execution.html
7-
65925f1af21c535ad347f6db8a7d7f73df95cdca2435401e227d6710bcb562fa gencode/docs/configuration_pubber.html
7+
366b0927ba7cec795ee9c84e04bbe9fddbcb796166f413c12e217ba31dac0a5e gencode/docs/configuration_pubber.html
88
a2851c70bd7c7787f760db9e8b29f8604a606dcdf1d7447da363ddf354ff3669 gencode/docs/envelope.html
99
41d26633d8592eabd36cbb8344884cc04ee93bbac942dd73336206d34dad0f93 gencode/docs/event.html
1010
c392f72cc92525587e8473354f2d8827096c68d2e418ad8f4121136be98aeb52 gencode/docs/event_discovery.html
@@ -92,7 +92,7 @@ fc3a9415c04d8a06954dbdbfdff5d68ab113cce3948532c19df555778ffb04fa gencode/java/u
9292
ca2e7566106818ca7e5190c8041eb86f0c9b3251b0bda8c3ea7ce11a0c891a0a gencode/java/udmi/schema/Position.java
9393
3df66bb1a37a9e0b2b6cf392f8c64d404a73c83e5e13c02bb4844f09b9a04b70 gencode/java/udmi/schema/Properties.java
9494
783320700f7e96cf8e421461f14999afca10cd540ca6aadf184add39f0ac048c gencode/java/udmi/schema/PubberConfiguration.java
95-
11c0149a3d4ca7bf069b6699b19a26a401bc611fb17c2d8c97f4844cc6054feb gencode/java/udmi/schema/PubberOptions.java
95+
95bf2511d6f598bcda4bf70c0181e3b902219128188d482d69d6a7313c587c42 gencode/java/udmi/schema/PubberOptions.java
9696
4604c0aab7cf63af4523e57a52e971013398adb5558500d7a453db49b8e1995a gencode/java/udmi/schema/ReflectorConfig.java
9797
abe99dd74122c186403baa6982300a9d5968f8bbb7a67b1689104111b98f32fb gencode/java/udmi/schema/ReflectorState.java
9898
4983cc00c17d11346a0353e7af726cd302e84ff4a1eabb7efcf2f4289b4ba81e gencode/java/udmi/schema/SequenceValidationState.java
@@ -165,7 +165,7 @@ ee9c02c35438fb7d9aacb15a21ec7b35b533c1000d0bde044ec3923b1fdccca4 gencode/python
165165
15b349141ebae651c6c3c5c313b197d49c8b2b44e8ff1b0639848ad42e5c4e63 gencode/python/udmi/schema/model_system_hardware.py
166166
aafe6e70c281152db958adf77a024e3e9fab8293927106297c5ec48c11f54e27 gencode/python/udmi/schema/model_testing.py
167167
5c50847e136a033ea511209238bb570499b43fbee6189dae06603132dcb9f01f gencode/python/udmi/schema/model_testing_target.py
168-
e4ecd1c86af0e5e0c249efc9924c1187fb44d368c99e76c68def5d1c96cf8378 gencode/python/udmi/schema/options_pubber.py
168+
61149ec70e1e47ba4b6f4c8f450567ff9de15509f4fa7a17b831660e5b63fd02 gencode/python/udmi/schema/options_pubber.py
169169
6c5f3dd1c5ca9d821e3c48298af118fc7eafd97af9265dfd34b2ed8642efca77 gencode/python/udmi/schema/persistent_device.py
170170
a58f8c98e837a5b56126ca0f410e02f1e9cfcd80a8cb429e0ef522defab1f690 gencode/python/udmi/schema/properties.py
171171
7fd3cd24bc9704778eba11696d21c4e88a35aea6e37e468d88666bc40eaafbad gencode/python/udmi/schema/reflect_config.py

etc/test_itemized.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
TEST broken_config configStateDelay RESULT pass system broken_config ALPHA 5 Sequence complete
12
TEST endpoint_failure_and_restart RESULT fail endpoint endpoint_failure_and_restart DISABLED 5 timeout waiting for system mode is INITIAL
23
TEST valid_serial_no noLastStart RESULT pass system valid_serial_no ALPHA 5 Sequence complete
34
TEST writeback_success noWriteback RESULT fail writeback writeback_success ALPHA 5 timeout waiting for point filter_differential_pressure_setpoint to have value_state applied

gencode/docs/configuration_pubber.html

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gencode/java/udmi/schema/PubberOptions.java

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gencode/python/udmi/schema/options_pubber.py

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pubber/src/main/java/daq/pubber/Pubber.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static com.google.common.base.Preconditions.checkArgument;
44
import static com.google.common.base.Preconditions.checkNotNull;
5+
import static com.google.common.base.Preconditions.checkState;
56
import static com.google.udmi.util.GeneralUtils.deepCopy;
67
import static com.google.udmi.util.GeneralUtils.fromJsonFile;
78
import static com.google.udmi.util.GeneralUtils.fromJsonString;
@@ -171,6 +172,7 @@ public class Pubber {
171172
private static final long BYTES_PER_MEGABYTE = 1024 * 1024;
172173
private static final String CORRUPT_STATE_MESSAGE = "!&*@(!*&@!";
173174
private static final long INJECT_MESSAGE_DELAY_MS = 2000; // Delay to make sure testing is stable.
175+
private static final int FORCED_STATE_TIME_MS = 10000;
174176
final State deviceState = new State();
175177
private final File outDir;
176178
private final ScheduledExecutorService executor = new CatchingScheduledThreadPoolExecutor(1);
@@ -936,13 +938,32 @@ private void publisherHandler(String type, String phase, Throwable cause) {
936938
publishLogMessage(report);
937939
// TODO: Replace this with a heap so only the highest-priority status is reported.
938940
deviceState.system.status = shouldLogLevel(report.level) ? report : null;
939-
publishAsynchronousState();
941+
publishConfigStateUpdate();
940942
if (cause != null && configLatch.getCount() > 0) {
941943
configLatch.countDown();
942944
warn("Released startup latch because reported error");
943945
}
944946
}
945947

948+
/**
949+
* Issue a state update in response to a received config message. This will optionally
950+
* add a synthetic delay in so that testing infrastructure can test that related sequence
951+
* tests handle this case appropriately.
952+
*/
953+
private void publishConfigStateUpdate() {
954+
if (TRUE.equals(configuration.options.configStateDelay)) {
955+
delayNextStateUpdate();
956+
}
957+
publishAsynchronousState();
958+
}
959+
960+
private void delayNextStateUpdate() {
961+
// Calculate a synthetic last state time that factors in the optional delay.
962+
long syntheticType = System.currentTimeMillis() - STATE_THROTTLE_MS + FORCED_STATE_TIME_MS;
963+
// And use the synthetic time iff it's later than the actual last state time.
964+
lastStateTimeMs = Math.max(lastStateTimeMs, syntheticType);
965+
}
966+
946967
private boolean shouldLogLevel(int level) {
947968
Integer minLoglevel = deviceConfig.system == null ? null : deviceConfig.system.min_loglevel;
948969
return level >= (minLoglevel == null ? Level.INFO.value() : minLoglevel);
@@ -986,7 +1007,7 @@ private void configHandler(Config config) {
9861007
} catch (Exception e) {
9871008
publisherConfigLog("apply", e);
9881009
}
989-
publishAsynchronousState();
1010+
publishConfigStateUpdate();
9901011
}
9911012

9921013
private void processConfigUpdate(Config config) {
@@ -1494,7 +1515,8 @@ private void publishLogMessage(Entry report) {
14941515
private void publishAsynchronousState() {
14951516
if (stateLock.tryAcquire()) {
14961517
try {
1497-
long delay = lastStateTimeMs + STATE_THROTTLE_MS - System.currentTimeMillis();
1518+
long soonestAllowedStateUpdate = lastStateTimeMs + STATE_THROTTLE_MS;
1519+
long delay = soonestAllowedStateUpdate - System.currentTimeMillis();
14981520
debug(String.format("State update defer %dms", delay));
14991521
if (delay > 0) {
15001522
markStateDirty(delay);
@@ -1545,7 +1567,6 @@ private void publishStateMessage(Object stateToSend) {
15451567
warn(String.format("State update delay %dms", delay));
15461568
safeSleep(delay);
15471569
}
1548-
15491570
lastStateTimeMs = System.currentTimeMillis();
15501571
CountDownLatch latch = new CountDownLatch(1);
15511572
publishDeviceMessage(stateToSend, () -> {

schema/options_pubber.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
"extraPoint": {
2929
"type": "string"
3030
},
31+
"configStateDelay": {
32+
"type": "boolean"
33+
},
3134
"missingPoint": {
3235
"type": "string"
3336
},

validator/src/main/java/com/google/daq/mqtt/sequencer/SequenceBase.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public class SequenceBase {
104104

105105
private static final int FUNCTIONS_VERSION_BETA = Validator.REQUIRED_FUNCTION_VER;
106106
private static final int FUNCTIONS_VERSION_ALPHA = 6; // Version required for alpha execution.
107+
private static final long CONFIG_BARRIER_MS = 1000;
107108

108109
static {
109110
// Sanity check to make sure ALPHA version is increased if forced by increased BETA.
@@ -723,6 +724,8 @@ private void assertConfigIsNotPending() {
723724

724725
protected void updateConfig(String reason) {
725726
assertConfigIsNotPending();
727+
// Add a forced sleep to make sure second-quantized timestamps are unique.
728+
safeSleep(CONFIG_BARRIER_MS);
726729
updateConfig(SubFolder.SYSTEM, augmentConfig(deviceConfig.system));
727730
updateConfig(SubFolder.POINTSET, deviceConfig.pointset);
728731
updateConfig(SubFolder.GATEWAY, deviceConfig.gateway);
@@ -1346,6 +1349,12 @@ protected void checkThatHasInterestingSystemStatus(boolean isInteresting) {
13461349
check.accept("interesting system status", this::hasInterestingSystemStatus);
13471350
}
13481351

1352+
protected void untilHasInterestingSystemStatus(boolean isInteresting) {
1353+
BiConsumer<String, Supplier<Boolean>> until =
1354+
isInteresting ? this::untilTrue : this::untilFalse;
1355+
until.accept("interesting system status", this::hasInterestingSystemStatus);
1356+
}
1357+
13491358
/**
13501359
* Add a summary of a test, with a simple description of what it's testing.
13511360
*/

validator/src/main/java/com/google/daq/mqtt/sequencer/sequences/ConfigSequences.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void broken_config() {
9191

9292
setExtraField("break_json");
9393
untilLogged(SYSTEM_CONFIG_RECEIVE, SYSTEM_CONFIG_RECEIVE_LEVEL);
94-
checkThatHasInterestingSystemStatus(true);
94+
untilHasInterestingSystemStatus(true);
9595
Entry stateStatus = deviceState.system.status;
9696
info("Error message: " + stateStatus.message);
9797
debug("Error detail: " + stateStatus.detail);
@@ -106,14 +106,19 @@ public void broken_config() {
106106
untilLogged(SYSTEM_CONFIG_PARSE, Level.ERROR);
107107
checkNotLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL);
108108

109+
// Will restore min_loglevel to the default of INFO.
109110
resetConfig(); // clears extra_field
111+
untilLogged(SYSTEM_CONFIG_RECEIVE, SYSTEM_CONFIG_RECEIVE_LEVEL);
112+
untilLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL);
113+
110114
deviceConfig.system.min_loglevel = Level.DEBUG.value();
111115
checkThatHasInterestingSystemStatus(false);
112116
untilTrue("last_config updated",
113117
() -> !dateEquals(stableConfig, deviceState.system.last_config)
114118
);
115119
assertTrue("system operational", deviceState.system.operation.operational);
116120
untilLogged(SYSTEM_CONFIG_APPLY, SYSTEM_CONFIG_APPLY_LEVEL);
121+
// These should not be logged since the level was at INFO until the new config is applied.
117122
checkNotLogged(SYSTEM_CONFIG_RECEIVE, SYSTEM_CONFIG_RECEIVE_LEVEL);
118123
checkNotLogged(SYSTEM_CONFIG_PARSE, SYSTEM_CONFIG_PARSE_LEVEL);
119124
}

0 commit comments

Comments
 (0)