Skip to content

Commit cc67155

Browse files
Generalise logging expectations
1 parent 17e6bd6 commit cc67155

File tree

1 file changed

+21
-197
lines changed
  • server/src/internalClusterTest/java/org/elasticsearch/cluster/coordination

1 file changed

+21
-197
lines changed

server/src/internalClusterTest/java/org/elasticsearch/cluster/coordination/NodeJoiningIT.java

Lines changed: 21 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -62,35 +62,23 @@ public void testNodeJoinsCluster() {
6262
try {
6363
ensureSufficientMasterEligibleNodes();
6464
String masterNodeName = internalCluster().getMasterName();
65-
DiscoveryNode masterNode = internalCluster().clusterService(masterNodeName).state().nodes().getMasterNode();
6665
int numberOfNodesOriginallyInCluster = internalCluster().clusterService(masterNodeName).state().getNodes().size();
6766
int numberOfMasterNodesOriginallyInCluster = internalCluster().clusterService(masterNodeName).state().nodes().getMasterNodes().size();
6867
List<String> namesOfDataNodesInOriginalCluster = getListOfDataNodeNamesFromCluster(masterNodeName);
6968

70-
// Ensure the logging is as expected
71-
try (var mockLog = MockLog.capture(NodeJoinExecutor.class)) {
72-
assert masterNode != null;
73-
String expectedNewNodeAsString = generateNodeDescriptionForNewDiscoveryNode(numberOfNodesOriginallyInCluster, masterNode);
74-
75-
// We expect to see a node join message from the new node
76-
addNodeJoinExpectation(mockLog, expectedNewNodeAsString);
77-
78-
// Attempt to add new node
79-
String newNodeName = internalCluster().startDataOnlyNode();
80-
81-
mockLog.assertAllExpectationsMatched();
69+
// Attempt to add new node
70+
String newNodeName = internalCluster().startDataOnlyNode();
8271

83-
// Assert the new data node was added
84-
ClusterState state = internalCluster().clusterService(masterNodeName).state();
85-
assertEquals(numberOfNodesOriginallyInCluster + 1, state.nodes().getSize());
86-
assertEquals(namesOfDataNodesInOriginalCluster.size() + 1, state.nodes().getDataNodes().size());
87-
assertEquals(numberOfMasterNodesOriginallyInCluster, state.nodes().getMasterNodes().size());
72+
// Assert the new data node was added
73+
ClusterState state = internalCluster().clusterService(masterNodeName).state();
74+
assertEquals(numberOfNodesOriginallyInCluster + 1, state.nodes().getSize());
75+
assertEquals(namesOfDataNodesInOriginalCluster.size() + 1, state.nodes().getDataNodes().size());
76+
assertEquals(numberOfMasterNodesOriginallyInCluster, state.nodes().getMasterNodes().size());
8877

89-
List<String> namesOfDataNodesInNewCluster = getListOfDataNodeNamesFromCluster(masterNodeName);
90-
assertTrue(namesOfDataNodesInNewCluster.contains(newNodeName));
91-
for (String nodeName : namesOfDataNodesInOriginalCluster) {
92-
assertTrue(namesOfDataNodesInNewCluster.contains(nodeName));
93-
}
78+
List<String> namesOfDataNodesInNewCluster = getListOfDataNodeNamesFromCluster(masterNodeName);
79+
assertTrue(namesOfDataNodesInNewCluster.contains(newNodeName));
80+
for (String nodeName : namesOfDataNodesInOriginalCluster) {
81+
assertTrue(namesOfDataNodesInNewCluster.contains(nodeName));
9482
}
9583
} finally {
9684
Releasables.closeExpectNoException(Releasables.wrap(cleanupTasks));
@@ -111,7 +99,6 @@ public void testNodeTriesToJoinClusterAndThenDifferentMasterIsElected() {
11199
int numberOfNodesOriginallyInCluster = internalCluster().clusterService(originalMasterNodeName).state().getNodes().size();
112100
int numberOfMasterNodesOriginallyInCluster = internalCluster().clusterService(originalMasterNodeName).state().nodes().getMasterNodes().size();
113101
List<String> namesOfDataNodesInOriginalCluster = getListOfDataNodeNamesFromCluster(originalMasterNodeName);
114-
DiscoveryNode masterNode = internalCluster().clusterService(originalMasterNodeName).state().getNodes().getMasterNode();
115102

116103
// Sets MockTransportService behaviour
117104
for (final var transportService : internalCluster().getInstances(TransportService.class)) {
@@ -135,14 +122,8 @@ public void testNodeTriesToJoinClusterAndThenDifferentMasterIsElected() {
135122

136123
// Ensure the logging is as expected
137124
try (var mockLog = MockLog.capture(NodeJoinExecutor.class)) {
138-
assert masterNode != null;
139-
String expectedNewNodeAsString = generateNodeDescriptionForNewDiscoveryNode(numberOfNodesOriginallyInCluster, masterNode);
140-
141-
// We expect to see a node join message from the new node
142-
addNodeJoinExpectation(mockLog, expectedNewNodeAsString);
143-
144-
// We do not expect to see the WARN log
145-
addJoiningNodeDisconnectedWarnLogExpectation(mockLog, expectedNewNodeAsString);
125+
// We do not expect to see a WARN log about a node disconnecting (#ES-11449)
126+
addJoiningNodeDisconnectedWarnLogFalseExpectation(mockLog);
146127

147128
// We haven't changed master nodes yet
148129
assertEquals(originalMasterNodeName, internalCluster().getMasterName());
@@ -183,7 +164,7 @@ public void testNodeTriesToJoinClusterAndThenDifferentMasterIsElected() {
183164

184165
/*
185166
In this scenario, node N attempts to join a cluster, there is an election and the original master is re-elected.
186-
Node N should join the cluster, but it should not be disconnected
167+
Node N should join the cluster, but it should not be disconnected (#ES-11449)
187168
*/
188169
@TestLogging(
189170
reason = "test includes assertions about logging",
@@ -202,7 +183,6 @@ public void testNodeTriesToJoinClusterAndThenSameMasterIsElected() {
202183
DiscoveryNode masterNode = internalCluster().clusterService(masterNodeName).state().nodes().getMasterNode();
203184

204185
long originalTerm = internalCluster().clusterService(masterNodeName).state().coordinationMetadata().term();
205-
long originalVersion = internalCluster().clusterService(masterNodeName).state().version();
206186
int numberOfNodesOriginallyInCluster = internalCluster().clusterService(masterNodeName).state().getNodes().size();
207187
int numberOfMasterNodesOriginallyInCluster = internalCluster().clusterService(masterNodeName).state().nodes().getMasterNodes().size();
208188
List<String> namesOfDataNodesInOriginalCluster = getListOfDataNodeNamesFromCluster(masterNodeName);
@@ -246,32 +226,16 @@ public void testNodeTriesToJoinClusterAndThenSameMasterIsElected() {
246226

247227
// Ensure the logging is as expected
248228
try (var mockLog = MockLog.capture(NodeJoinExecutor.class, MasterService.class, ClusterApplierService.class)) {
249-
long firstNodeJoinVersion = originalVersion + 1;
250229
assert masterNode != null;
251-
String expectedNewNodeAsString = generateNodeDescriptionForNewDiscoveryNode(numberOfNodesOriginallyInCluster, masterNode);
252-
253-
/*
254-
We expect to see a node join event as the master tries to process the join,
255-
but cannot commit the cluster state due to a lack of quorum.
256-
This means the join is not successful in this term.
257-
*/
258-
addMasterServiceUpdateTaskNodeJoinExpectation(mockLog, expectedNewNodeAsString, originalTerm, firstNodeJoinVersion);
259230

260-
// The node join fails
261-
addFailedToCommitClusterStateVersionExpectation(mockLog, expectedNewNodeAsString, firstNodeJoinVersion);
231+
// We expect the node join to fail
232+
addFailedToCommitClusterStateExpectation(mockLog);
262233

263234
/*
264235
We expect the cluster to reuse the connection to N and not disconnect it
265236
Therefore, this WARN log should not be thrown
266237
*/
267-
addJoiningNodeDisconnectedWarnLogExpectation(mockLog, expectedNewNodeAsString);
268-
269-
/*
270-
We expect node N to join the cluster.
271-
However, we expect no explicit `node-join: [{node_s5} ...]` log to be emitted by the master in this new term
272-
as the join is processed as part of the new election and cluster state publication, rather than a separate event
273-
*/
274-
addNodeJoinProcessedDuringNewElectionAndClusterStatePublicationExpectation(mockLog, expectedNewNodeAsString);
238+
addJoiningNodeDisconnectedWarnLogFalseExpectation(mockLog);
275239

276240
// Before we add the new node, assert we haven't changed master nodes yet
277241
assertEquals(masterNodeName, internalCluster().getMasterName());
@@ -350,77 +314,7 @@ private boolean nodeExistsWithName(DiscoveryNodes nodes, String nodeName) {
350314
return false;
351315
}
352316

353-
private void addNodeJoinExpectation(MockLog mockLog, String expectedNewNodeAsString) {
354-
// This matches with the node join message from the new node only
355-
mockLog.addExpectation(new MockLog.LoggingExpectation() {
356-
boolean matched = false;
357-
358-
@Override
359-
public void match(LogEvent event) {
360-
if (event.getLevel() != Level.INFO) {
361-
return;
362-
}
363-
if (event.getLoggerName().equals(NodeJoinExecutor.class.getCanonicalName()) == false) {
364-
return;
365-
}
366-
367-
Pattern pattern = Pattern.compile("node-join: \\[" + expectedNewNodeAsString + "] " + "with reason \\[joining]");
368-
Matcher matcher = pattern.matcher(event.getMessage().getFormattedMessage());
369-
370-
if (matcher.find()) {
371-
matched = true;
372-
}
373-
}
374-
375-
@Override
376-
public void assertMatched() {
377-
assertTrue(matched);
378-
}
379-
});
380-
}
381-
382-
private void addMasterServiceUpdateTaskNodeJoinExpectation(MockLog mockLog, String expectedNewNodeAsString, long term, long version) {
383-
mockLog.addExpectation(new MockLog.LoggingExpectation() {
384-
boolean matched = false;
385-
386-
@Override
387-
public void match(LogEvent event) {
388-
if (event.getLevel() != Level.INFO) {
389-
return;
390-
}
391-
if (event.getLoggerName().equals(MasterService.class.getCanonicalName()) == false) {
392-
return;
393-
}
394-
395-
Pattern pattern = Pattern.compile(
396-
"node-join\\["
397-
+ expectedNewNodeAsString
398-
+ " joining],"
399-
+ " term: "
400-
+ term
401-
+ ","
402-
+ " version: "
403-
+ version
404-
+ ","
405-
+ " delta: added \\{"
406-
+ expectedNewNodeAsString
407-
+ "}"
408-
);
409-
Matcher matcher = pattern.matcher(event.getMessage().getFormattedMessage());
410-
411-
if (matcher.find()) {
412-
matched = true;
413-
}
414-
}
415-
416-
@Override
417-
public void assertMatched() {
418-
assertTrue(matched);
419-
}
420-
});
421-
}
422-
423-
private void addFailedToCommitClusterStateVersionExpectation(MockLog mockLog, String expectedNewNodeAsString, long version) {
317+
private void addFailedToCommitClusterStateExpectation(MockLog mockLog) {
424318
mockLog.addExpectation(new MockLog.LoggingExpectation() {
425319
boolean matched = false;
426320

@@ -433,13 +327,7 @@ public void match(LogEvent event) {
433327
return;
434328
}
435329

436-
Pattern pattern = Pattern.compile(
437-
"failing \\[node-join\\["
438-
+ expectedNewNodeAsString
439-
+ " joining]]: failed to commit cluster state version \\["
440-
+ version
441-
+ "]"
442-
);
330+
Pattern pattern = Pattern.compile("failed to commit cluster state");
443331
Matcher matcher = pattern.matcher(event.getMessage().getFormattedMessage());
444332

445333
if (matcher.find()) {
@@ -454,7 +342,7 @@ public void assertMatched() {
454342
});
455343
}
456344

457-
private void addJoiningNodeDisconnectedWarnLogExpectation(MockLog mockLog, String expectedNewNodeAsString) {
345+
private void addJoiningNodeDisconnectedWarnLogFalseExpectation(MockLog mockLog) {
458346
mockLog.addExpectation(new MockLog.LoggingExpectation() {
459347
boolean matched = false;
460348

@@ -470,7 +358,7 @@ public void match(LogEvent event) {
470358
String regexToMatchAnyCharacterExceptClosingBrace = "([^}]+)";
471359
Pattern pattern = Pattern.compile(
472360
"node-join: \\["
473-
+ expectedNewNodeAsString
361+
+ regexToMatchAnyCharacterExceptClosingBrace
474362
+ "] "
475363
+ "with reason \\[joining, removed \\["
476364
+ regexToMatchAnyCharacterExceptClosingBrace
@@ -492,70 +380,6 @@ public void assertMatched() {
492380
});
493381
}
494382

495-
private void addNodeJoinProcessedDuringNewElectionAndClusterStatePublicationExpectation(
496-
MockLog mockLog,
497-
String expectedNewNodeAsString
498-
) {
499-
mockLog.addExpectation(new MockLog.LoggingExpectation() {
500-
boolean matched = false;
501-
502-
@Override
503-
public void match(LogEvent event) {
504-
if (event.getLevel() != Level.INFO) {
505-
return;
506-
}
507-
if (event.getLoggerName().equals(ClusterApplierService.class.getCanonicalName()) == false) {
508-
return;
509-
}
510-
511-
Pattern pattern = Pattern.compile("added \\{" + expectedNewNodeAsString + "}");
512-
Matcher matcher = pattern.matcher(event.getMessage().getFormattedMessage());
513-
514-
if (matcher.find()) {
515-
matched = true;
516-
}
517-
}
518-
519-
@Override
520-
public void assertMatched() {
521-
assertTrue(matched);
522-
}
523-
});
524-
}
525-
526-
private String generateNodeDescriptionForNewDiscoveryNode(int numberOfNodesOriginallyInCluster, DiscoveryNode masterNode) {
527-
// Nodes are named `node_s0`, `node_s1` etc ...
528-
// Therefore, if there are N nodes in the cluster, named `node_s0` ... `node_sN-1`, N+1 will be named `node_sN`
529-
String newNodeName = "node_s" + numberOfNodesOriginallyInCluster;
530-
String regexToMatchAnyCharacterExceptClosingBrace = "([^}]+)";
531-
532-
return "\\{"
533-
+ newNodeName
534-
+ "}"
535-
+ "\\{"
536-
+ regexToMatchAnyCharacterExceptClosingBrace
537-
+ "}"
538-
+ "\\{"
539-
+ regexToMatchAnyCharacterExceptClosingBrace
540-
+ "}"
541-
+ "\\{"
542-
+ newNodeName
543-
+ "}"
544-
+ "\\{"
545-
+ masterNode.getHostAddress()
546-
+ "}"
547-
+ "\\{"
548-
+ masterNode.getHostAddress()
549-
+ ":\\d+}"
550-
+ "\\{d}"
551-
+ "\\{"
552-
+ masterNode.getVersion()
553-
+ "}"
554-
+ "\\{"
555-
+ regexToMatchAnyCharacterExceptClosingBrace
556-
+ "}";
557-
}
558-
559383
/**
560384
* Removes all custom mockTransportService.addSendBehavior so that the original master node can run for election
561385
*

0 commit comments

Comments
 (0)