1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2025-09-09 18:29:45 +02:00

[core] Introduce Builder.failOnUnknownStates() and unit tests

The previous approach of emitting a severe log message when a
state (descriptor) was unknown was misleading. There are valid cases
where some states are not known, if, for example, a module was
explicitly disabled.

Using Builder.failOnUnknownStates() in unit tests is far cleaner, as
the existence of unknown states is tested in a controlled environment:
one where are states are supposed to be known.
This commit is contained in:
Florian Schmaus 2021-07-06 14:06:39 +02:00
parent b6c8754012
commit d33a5a23c3
3 changed files with 52 additions and 17 deletions

View file

@ -54,7 +54,7 @@ public final class ModularXmppClientToServerConnectionConfiguration extends Conn
}
try {
initialStateDescriptorVertex = StateDescriptorGraph.constructStateDescriptorGraph(backwardEdgeStateDescriptors);
initialStateDescriptorVertex = StateDescriptorGraph.constructStateDescriptorGraph(backwardEdgeStateDescriptors, builder.failOnUnknownStates);
}
catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
@ -91,6 +91,8 @@ public final class ModularXmppClientToServerConnectionConfiguration extends Conn
private final Map<Class<? extends ModularXmppClientToServerConnectionModuleDescriptor>, ModularXmppClientToServerConnectionModuleDescriptor> modulesDescriptors = new HashMap<>();
private boolean failOnUnknownStates;
private Builder() {
SmackConfiguration.addAllKnownModulesTo(this);
}
@ -163,6 +165,17 @@ public final class ModularXmppClientToServerConnectionConfiguration extends Conn
return getThis();
}
/**
* Fail if there are unknown states in Smack's state descriptor graph. This method is used mostly for testing
* the internals of Smack. Users can safely ignore it.
*
* @return a reference to this builder.
*/
public Builder failOnUnknownStates() {
failOnUnknownStates = true;
return getThis();
}
@Override
protected Builder getThis() {
return this;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2018 Florian Schmaus
* Copyright 2018-2021 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,7 +28,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection.DisconnectedStateDescriptor;
import org.jivesoftware.smack.c2s.internal.ModularXmppClientToServerConnectionInternal;
@ -47,8 +46,6 @@ import org.jivesoftware.smack.util.MultiMap;
*/
public class StateDescriptorGraph {
private static final Logger LOGGER = Logger.getLogger(StateDescriptorGraph.class.getName());
private static GraphVertex<StateDescriptor> addNewStateDescriptorGraphVertex(
Class<? extends StateDescriptor> stateDescriptorClass,
Map<Class<? extends StateDescriptor>, GraphVertex<StateDescriptor>> graphVertexes)
@ -102,7 +99,8 @@ public class StateDescriptorGraph {
}
private static void handleStateDescriptorGraphVertex(GraphVertex<StateDescriptor> node,
HandleStateDescriptorGraphVertexContext context)
HandleStateDescriptorGraphVertexContext context,
boolean failOnUnknownStates)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Class<? extends StateDescriptor> stateDescriptorClass = node.element.getClass();
boolean alreadyHandled = context.recurseInto(stateDescriptorClass);
@ -126,7 +124,7 @@ public class StateDescriptorGraph {
case 1:
GraphVertex<StateDescriptor> soleSuccessorNode = successorStateDescriptors.values().iterator().next();
node.addOutgoingEdge(soleSuccessorNode);
handleStateDescriptorGraphVertex(soleSuccessorNode, context);
handleStateDescriptorGraphVertex(soleSuccessorNode, context, failOnUnknownStates);
return;
}
@ -144,9 +142,8 @@ public class StateDescriptorGraph {
StateDescriptor successorStateDescriptor = successorStateDescriptorGraphNode.element;
Class<? extends StateDescriptor> successorStateDescriptorClass = successorStateDescriptor.getClass();
for (Class<? extends StateDescriptor> subordinateClass : successorStateDescriptor.getSubordinates()) {
if (!successorClasses.contains(subordinateClass)) {
LOGGER.severe(successorStateDescriptor + " points to a subordinate '" + subordinateClass + "' which is not part of the successor set");
continue;
if (failOnUnknownStates && !successorClasses.contains(subordinateClass)) {
throw new IllegalStateException(successorStateDescriptor + " points to a subordinate '" + subordinateClass + "' which is not part of the successor set");
}
GraphVertex<Class<? extends StateDescriptor>> superiorClassNode = lookupAndCreateIfRequired(
@ -157,10 +154,9 @@ public class StateDescriptorGraph {
superiorClassNode.addOutgoingEdge(subordinateClassNode);
}
for (Class<? extends StateDescriptor> superiorClass : successorStateDescriptor.getSuperiors()) {
if (!successorClasses.contains(superiorClass)) {
LOGGER.severe(successorStateDescriptor + " points to a superior '" + superiorClass
if (failOnUnknownStates && !successorClasses.contains(superiorClass)) {
throw new IllegalStateException(successorStateDescriptor + " points to a superior '" + superiorClass
+ "' which is not part of the successor set");
continue;
}
GraphVertex<Class<? extends StateDescriptor>> subordinateClassNode = lookupAndCreateIfRequired(
@ -193,11 +189,13 @@ public class StateDescriptorGraph {
node.addOutgoingEdge(successorVertex);
// Recurse further.
handleStateDescriptorGraphVertex(successorVertex, context);
handleStateDescriptorGraphVertex(successorVertex, context, failOnUnknownStates);
}
}
public static GraphVertex<StateDescriptor> constructStateDescriptorGraph(Set<Class<? extends StateDescriptor>> backwardEdgeStateDescriptors)
public static GraphVertex<StateDescriptor> constructStateDescriptorGraph(
Set<Class<? extends StateDescriptor>> backwardEdgeStateDescriptors,
boolean failOnUnknownStates)
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException {
Map<Class<? extends StateDescriptor>, GraphVertex<StateDescriptor>> graphVertexes = new HashMap<>();
@ -219,7 +217,7 @@ public class StateDescriptorGraph {
}
HandleStateDescriptorGraphVertexContext context = new HandleStateDescriptorGraphVertexContext(graphVertexes, inferredForwardEdges);
handleStateDescriptorGraphVertex(initialNode, context);
handleStateDescriptorGraphVertex(initialNode, context, failOnUnknownStates);
return initialNode;
}