From a2faeb562725db8440ef4dd1aa7b4bc2f712831d Mon Sep 17 00:00:00 2001 From: Kristian Karl Date: Tue, 18 Feb 2020 17:51:29 +0100 Subject: [PATCH] Do not switch into context with available edges Fixed data logging Added debug loging --- .../core/machine/ExecutionContext.java | 29 +++++++++--- .../core/machine/SimpleMachine.java | 26 ++++++++--- .../core/machine/SimpleMachineTest.java | 45 +++++++++++++++++++ 3 files changed, 87 insertions(+), 13 deletions(-) diff --git a/graphwalker-core/src/main/java/org/graphwalker/core/machine/ExecutionContext.java b/graphwalker-core/src/main/java/org/graphwalker/core/machine/ExecutionContext.java index 1a1c90af2..bb293b405 100644 --- a/graphwalker-core/src/main/java/org/graphwalker/core/machine/ExecutionContext.java +++ b/graphwalker-core/src/main/java/org/graphwalker/core/machine/ExecutionContext.java @@ -258,8 +258,9 @@ public List filter(Collection elements) { public boolean isAvailable(RuntimeEdge edge) { if (edge.hasGuard()) { - LOG.debug("Execute: '{}' in model: '{}'", edge.getGuard().getScript(), getModel().getName()); + LOG.debug("Execute guard: '{}' in model: '{}'", edge.getGuard().getScript(), getModel().getName()); try { + LOG.debug("Guard: '{}' is: '{}'", edge.getGuard().getScript(), getScriptEngine().eval(edge.getGuard().getScript())); return (Boolean) getScriptEngine().eval(edge.getGuard().getScript()); } catch (ScriptException e) { LOG.error(e.getMessage()); @@ -270,17 +271,18 @@ public boolean isAvailable(RuntimeEdge edge) { } public void execute(Action action) { - LOG.debug("Execute: '{}' in model: '{}'", action.getScript(), getModel().getName()); + LOG.debug("Execute action: '{}' in model: '{}'", action.getScript(), getModel().getName()); try { getScriptEngine().eval(action.getScript()); } catch (ScriptException e) { LOG.error(e.getMessage()); throw new MachineException(this, e); } + LOG.debug("Data: '{}'", getKeys().toString()); } public void execute(String name) { - LOG.debug("Execute: '{}' in model: '{}'", name, getModel().getName()); + LOG.debug("Execute method: '{}' in model: '{}'", name, getModel().getName()); try { getClass().getMethod(name); // provoke a NoSuchMethodException exception if the method doesn't exist getScriptEngine().eval(name + "()"); @@ -310,9 +312,24 @@ public Map getKeys() { } } } - } else { - for (String key : getBindings(ENGINE_SCOPE).keySet()) { + } + + if (getBindings(ENGINE_SCOPE).containsKey("global")) { + Map global = (Map) getBindings(ENGINE_SCOPE).get("global"); + for (String key : global.keySet()) { if (isVariable(key, methods)) { + if (global.get(key) instanceof Double) { + keys.put(key, Long.toString(Math.round((double) global.get(key)))); + } else { + keys.put(key, global.get(key).toString()); + } + } + } + } + + if (keys.isEmpty()) { + for (String key : getBindings(ENGINE_SCOPE).keySet()) { + if (!"nashorn.global".equals(key) && !"global".equals(key) && isVariable(key, methods)) { Object value = getBindings(ENGINE_SCOPE).get(key); if (value instanceof Double) { keys.put(key, Long.toString(Math.round((double) value))); @@ -337,7 +354,7 @@ public Object getAttribute(String name) { @SuppressWarnings("unchecked") public void setAttribute(String name, Object value) { - if (getBindings(ENGINE_SCOPE).containsKey("nashorn.global")) { + if (getBindings(ENGINE_SCOPE).containsKey("global")) { Map attributes = (Map) getBindings(ENGINE_SCOPE).get("nashorn.global"); attributes.put(name, value); } else { diff --git a/graphwalker-core/src/main/java/org/graphwalker/core/machine/SimpleMachine.java b/graphwalker-core/src/main/java/org/graphwalker/core/machine/SimpleMachine.java index 16a74f162..305f79158 100644 --- a/graphwalker-core/src/main/java/org/graphwalker/core/machine/SimpleMachine.java +++ b/graphwalker-core/src/main/java/org/graphwalker/core/machine/SimpleMachine.java @@ -30,6 +30,7 @@ import org.graphwalker.core.generator.NoPathFoundException; import org.graphwalker.core.generator.SingletonRandomGenerator; import org.graphwalker.core.model.Action; +import org.graphwalker.core.model.Edge; import org.graphwalker.core.model.Element; import org.graphwalker.core.model.Requirement; import org.slf4j.Logger; @@ -212,12 +213,12 @@ private boolean hasPossibleSharedStates(RuntimeVertex vertex) { private List getPossibleSharedStates(String sharedState) { List sharedStates = new ArrayList<>(); for (Context context : getContexts()) { - if (getCurrentContext().equals(context) && hasOutEdges(context)) { + if (getCurrentContext().equals(context) && hasAccessibleOutEdges(context, context.getCurrentElement())) { sharedStates.add(new SharedStateTuple(getCurrentContext(), (RuntimeVertex) getCurrentContext().getCurrentElement())); } else if (!getCurrentContext().equals(context) && context.getModel().hasSharedState(sharedState)) { for (RuntimeVertex vertex : context.getModel().getSharedStates(sharedState)) { - if ((!vertex.equals(lastElement) || getCurrentContext().getModel().getOutEdges((RuntimeVertex) getCurrentContext().getCurrentElement()).isEmpty()) - && (vertex.hasName() || !context.getModel().getOutEdges(vertex).isEmpty())) { + if ((!vertex.equals(lastElement) || !hasAccessibleOutEdges(getCurrentContext(), getCurrentContext().getCurrentElement())) + && (vertex.hasName() || hasAccessibleOutEdges(context, vertex))) { sharedStates.add(new SharedStateTuple(context, vertex)); } } @@ -226,10 +227,21 @@ private List getPossibleSharedStates(String sharedState) { return sharedStates; } - private boolean hasOutEdges(Context context) { - return isNotNull(context.getCurrentElement()) - && context.getCurrentElement() instanceof RuntimeVertex - && !context.getModel().getOutEdges((RuntimeVertex) context.getCurrentElement()).isEmpty(); + private boolean hasAccessibleOutEdges(Context context, Element element) { + if (isNull(element)) { + return false; + } + + if (element instanceof RuntimeEdge) { + return false; + } + + for (RuntimeEdge edge : context.getModel().getOutEdges((RuntimeVertex) element)) { + if (context.isAvailable(edge)) { + return true; + } + } + return false; } @Override diff --git a/graphwalker-core/src/test/java/org/graphwalker/core/machine/SimpleMachineTest.java b/graphwalker-core/src/test/java/org/graphwalker/core/machine/SimpleMachineTest.java index 5df6b3660..a1c4ea67a 100644 --- a/graphwalker-core/src/test/java/org/graphwalker/core/machine/SimpleMachineTest.java +++ b/graphwalker-core/src/test/java/org/graphwalker/core/machine/SimpleMachineTest.java @@ -46,6 +46,7 @@ import org.graphwalker.core.generator.AStarPath; import org.graphwalker.core.generator.RandomPath; import org.graphwalker.core.generator.ShortestAllPaths; +import org.graphwalker.core.generator.SingletonRandomGenerator; import org.graphwalker.core.model.Action; import org.graphwalker.core.model.Edge; import org.graphwalker.core.model.Element; @@ -191,6 +192,50 @@ public void sharedState() throws Exception { assertThat(expectedPath, is(path)); } + @Test + public void sharedStateWithUnaccessibleEdge() throws Exception { + SingletonRandomGenerator.setSeed(147945811993279L); + + Vertex v1_A = new Vertex().setName("v1_A"); + Vertex v2_A = new Vertex().setSharedState("MyState").setName("v2_A"); + Edge e1_A = new Edge().setSourceVertex(v1_A).setTargetVertex(v2_A).setName("e1_A"); + Edge e2_A = new Edge().setSourceVertex(v2_A).setTargetVertex(v1_A).addAction(new Action("global.available = true")).setName("e2_A"); + + Vertex v1_B = new Vertex().setSharedState("MyState").setName("v1_B"); + Vertex v2_B = new Vertex().setName("v2_B"); + Edge e1_B = new Edge().setSourceVertex(v1_B).setTargetVertex(v2_B).setGuard(new Guard("global.available == true")); + + Model m1 = new Model().addEdge(e1_A).addEdge(e2_A).addAction(new Action("global.available = false")).setName("m1");; + Model m2 = new Model().addEdge(e1_B).setName("m2"); + + List contexts = new ArrayList<>(); + contexts.add(new TestExecutionContext(m1, new RandomPath(new VertexCoverage(100))).setNextElement(v1_A)); + contexts.add(new TestExecutionContext(m2, new RandomPath(new VertexCoverage(100)))); + + Machine machine = new SimpleMachine(contexts); + while (machine.hasNextStep()) { + machine.getNextStep(); + } + + List expectedPath = Arrays.asList( + v1_A.build(), + e1_A.build(), + v2_A.build(), + v1_B.build(), + v2_A.build(), + e2_A.build(), + v1_A.build(), + e1_A.build(), + v2_A.build(), + v1_B.build(), + e1_B.build(), + v2_B.build()); + + List path = machine.getProfiler().getExecutionPath().stream() + .map(Execution::getElement).collect(Collectors.toList()); + assertThat(expectedPath, is(path)); + } + @Test(expected = MachineException.class) public void singleSharedStates() throws Exception { Vertex start = new Vertex();