/** * Manual injection of mocks. * */ @BeforeMethod public void init() throws Exception { session = new Session<>(sessionContext, resultCollector); }
@Test public void fromPassivate() throws SessionException, IllegalArgumentException, IllegalAccessException { stateField.set(session, State.PASSIVATED); String input = "Input"; session.activate(input, Session.EMPTY_SESSION_VARIABLES); assertThat(session.getState(), equalTo(Session.State.ACTIVATED)); verify(sessionContext, times(1)).activate(input, Session.EMPTY_SESSION_VARIABLES); }
@Test(dataProvider = "allStates") public void testFromDifferentStates(State state) throws IllegalArgumentException, IllegalAccessException { stateField.set(session, state); session.passivate(); assertThat(session.getState(), equalTo(Session.State.PASSIVATED)); verify(sessionContext, times(1)).passivate(); } }
@Test public void ruleWithConditionFailure() throws Exception { session = new Session<>(Rules.define(RuleA.class, RuleG.class), new DefaultSessionResultCollector<String>()); String input = "input"; session.activate(input, Session.EMPTY_SESSION_VARIABLES); DefaultSessionResult<String> result = session.call(); assertThat(session.getState(), equalTo(State.PROCESSED)); assertThat(result.getConditionFailures().keySet(), containsInAnyOrder("RuleG")); assertThat(result.getEndTags().keySet(), hasSize(1)); assertThat(result.getEndTags().keySet(), containsInAnyOrder("A")); }
Collection<RuleDefinition> nextRules = findNextRules(sessionContext.getStorage().getAvailableTagTypes(), sessionContext.getRuleSet()); try { Collection<RuleInput> inputs = collectInputs(ruleDef, sessionContext.getStorage()); inputs = filterProcessedInputs(sessionContext.getExecutions(), ruleDef, inputs); if (CollectionUtils.isNotEmpty(inputs)) { failure(ex); nextRules = findNextRules(sessionContext.getStorage().getAvailableTagTypes(), sessionContext.getRuleSet()); } else { break;
@Test(expectedExceptions = { SessionException.class }) public void withRuleException() throws Exception { session = new Session<>(Rules.define(RuleA.class, RuleD.class), new DefaultSessionResultCollector<String>()); String input = "input"; session.activate(input, Session.EMPTY_SESSION_VARIABLES); session.call(); } }
@Test public void singleTagTypeSingleInput() throws RuleDefinitionException, SessionException { RuleDefinition ruleB = Rules.define(RuleB.class); Tag rootTag = Tags.rootTag("input"); Tag tagA = Tags.tag("A", "input", rootTag); RuleOutput outputA = new RuleOutput("RuleA", "A", Collections.<ConditionFailure> emptyList(), Collections.singletonList(tagA)); when(outputStorage.findLatestResultsByTagType(Matchers.<Set<String>> anyObject())).thenReturn(Collections.singleton(outputA)); List<RuleInput> ruleInputs = new ArrayList<>(session.collectInputs(ruleB, outputStorage)); assertThat(ruleInputs, hasSize(1)); assertThat(ruleInputs.get(0).getRoot(), equalTo(tagA)); }
@Test public void makeValid() throws Exception { Set<Class<?>> ruleClasses = new HashSet<>(Arrays.asList(RuleA.class, RuleB.class, RuleC.class)); when(config.getRuleClasses()).thenReturn(ruleClasses); when(config.getResultCollector()).thenReturn(resultCollector); Answer<Class<? extends IRuleOutputStorage>> callableAnswer = new Answer<Class<? extends IRuleOutputStorage>>() { @Override public Class<? extends IRuleOutputStorage> answer(InvocationOnMock invocation) throws Throwable { return DefaultRuleOutputStorage.class; } }; doAnswer(callableAnswer).when(config).getStorageClass(); sessionFactory = new SessionFactory<>(config); Session<String, DefaultSessionResult<String>> session = sessionFactory.makeObject(); assertThat(session.getState(), equalTo(State.NEW)); assertThat(session.getSessionContext().getRuleSet(), empty()); session.activate("input", Collections.<String, Object> emptyMap()); assertThat(session.getState(), equalTo(State.ACTIVATED)); assertThat(session.getSessionContext().getRuleSet(), containsInAnyOrder(Rules.define(RuleA.class, RuleB.class, RuleC.class).toArray())); }
@Test public void allRulesMatch() throws RuleDefinitionException { Set<RuleDefinition> ruleDefinitions = Rules.define(RuleA.class, RuleB.class, RuleC.class); Set<String> availableTagTypes = new HashSet<>(Arrays.asList(Tags.ROOT_TAG, "A", "B")); Collection<RuleDefinition> nextRules = session.findNextRules(availableTagTypes, ruleDefinitions); assertThat(nextRules, containsInAnyOrder(ruleDefinitions.toArray(new RuleDefinition[0]))); }
@Override public void passivateObject(Session<I, R> session) throws Exception { session.passivate(); }
@Test public void filterAll() throws RuleDefinitionException, SessionException { RuleDefinition ruleB = Rules.define(RuleB.class); RuleDefinition ruleA = Rules.define(RuleA.class); RuleInput inputA1 = new RuleInput(Tags.tag("A", "A1")); RuleInput inputA2 = new RuleInput(Tags.tag("A", "A2")); RuleInput inputA3 = new RuleInput(Tags.tag("A", "A3")); RuleInput inputB = new RuleInput(Tags.tag("B", "XY")); RuleInput inputC = new RuleInput(Tags.tag("C", "XY")); Collection<RuleInput> inputs = Arrays.asList(inputA1, inputA2, inputA3, inputB, inputC); Multimap<RuleDefinition, RuleInput> executions = ArrayListMultimap.create(); executions.put(ruleB, inputA1); executions.put(ruleB, inputA2); executions.put(ruleB, inputA3); executions.put(ruleB, inputB); executions.put(ruleB, inputC); inputs = session.filterProcessedInputs(executions, ruleB, inputs); assertThat(inputs, empty()); } }
/** * Since we want to activate our Session objects with parameters we need to add an additional * borrowObject method. This method used internally the GenericObjectPool#borrowObject method, * but invokes the parametrized {@link Session#activate(Object, Map<String, ?>)} method to * ensure a proper activation of the {@link Session}. * * @param input * The input object to analyzed * @param variables * The session variables valid for this session execution. * @return An activated and ready to use {@link Session} instance. * @see Session * @see GenericObjectPool * @throws Exception * in case of borrowing the session fails. */ public Session<I, R> borrowObject(I input, Map<String, ?> variables) throws Exception { try { return super.borrowObject().activate(input, variables); } catch (Exception e) { throw new RuntimeException("Failed to borrow object from SessionPool.", e); } }
@Override public void destroyObject(Session<I, R> session) throws Exception { session.destroy(); }
/** * Executes the Session. Invocation is exclusively possible if {@link Session} is in ACTIVATED * state, any other state forces a {@link SessionException}. Processing is enabled inserting a * initial RuleOutput to the {@link IRuleOutputStorage} which will act as input to further * rules. If processing completes without errors the {@link Session} enters PROCESSED state. In * any case of error it enters FAILURE state. * * @throws Exception * If Session lifecycle is in an invalid state. * @return The diagnosis result. */ @Override public R call() throws Exception { // Processes and collect results. // If a Session is used as Callable this call might horribly fail if sessions are not // retrieved from SessionPool and a sessions lifeCycle is neglected. But we have not chance // to activate a // session internally due to missing input information. So simply fail switch (state) { case ACTIVATED: sessionContext.getStorage().store(Rules.triggerRuleOutput(sessionContext.getInput())); doProcess(); state = State.PROCESSED; break; default: throw new SessionException("Session can not enter process stated from: " + state + " state. Ensure that Session is in ACTIVATED state before processing."); } return resultCollector.collect(sessionContext); }
@Test public void twoOfThreeRulesApply() throws Exception { session = new Session<>(Rules.define(RuleA.class, RuleE.class, RuleF.class), new DefaultSessionResultCollector<String>()); String input = "input"; session.activate(input, Session.EMPTY_SESSION_VARIABLES); DefaultSessionResult<String> result = session.call(); assertThat(session.getState(), equalTo(State.PROCESSED)); assertThat(result.getConditionFailures().keys(), empty()); assertThat(result.getEndTags().keySet(), hasSize(2)); assertThat(result.getEndTags().keySet(), containsInAnyOrder("A", "E")); }
@Test public void noMatch1() throws RuleDefinitionException, SessionException { RuleDefinition ruleC = Rules.define(RuleC.class); when(outputStorage.findLatestResultsByTagType(Matchers.<Set<String>> anyObject())).thenReturn(Collections.singleton(Rules.triggerRuleOutput("input"))); Collection<RuleInput> ruleInputs = session.collectInputs(ruleC, outputStorage); assertThat(ruleInputs, empty()); }
@Test public void onlyRuleBMatch() throws RuleDefinitionException { RuleDefinition ruleA = Rules.define(RuleA.class); RuleDefinition ruleB = Rules.define(RuleB.class); RuleDefinition ruleC = Rules.define(RuleC.class); Set<RuleDefinition> ruleDefinitions = new HashSet<>(Arrays.asList(ruleA, ruleB, ruleC)); Set<String> availableTagTypes = new HashSet<>(Arrays.asList(new String[] { "A" })); Collection<RuleDefinition> nextRules = session.findNextRules(availableTagTypes, ruleDefinitions); assertThat(nextRules, containsInAnyOrder(ruleB)); }
/** * Destroys this session. If the session was not yet passivated, it will be passivated in * advance. While the session is destroyed, the ExecutorService is shutdown and the * SessionContext is destroyed. After the session is destroyed it is unusable! * */ public void destroy() { switch (state) { case PROCESSED: // We can destroy the session but it was not yet passivated. To stay in sync with the // state lifeCycle we passivate first passivate(); break; case DESTROYED: LOG.warn("Failed destroying session. Session has already been destroyed!"); return; case NEW: case ACTIVATED: LOG.warn("Session is destroy before it was processed."); break; case FAILURE: case PASSIVATED: default: break; } state = State.DESTROYED; sessionContext = null; // NOPMD }