/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.tajo.rule; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import org.apache.hadoop.fs.Path; import org.apache.tajo.rule.EvaluationResult.EvaluationResultCode; import org.apache.tajo.rule.SelfDiagnosisRuleEngine.RuleWrapper; import org.apache.tajo.util.CommonTestingUtil; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; public class TestRuleSession { private static Path testPath; @BeforeClass public static void setUp() throws Exception { testPath = CommonTestingUtil.getTestDir(); } @AfterClass public static void tearDown() throws Exception { CommonTestingUtil.cleanupTestDir(testPath.toUri().getPath()); } @Test public void testGetCallerClassName() throws Exception { SelfDiagnosisRuleEngine ruleEngine = SelfDiagnosisRuleEngine.getInstance(); ruleEngine.reset(); SelfDiagnosisRuleSession ruleSession = ruleEngine.newRuleSession(); assertThat(ruleSession.getCallerClassName(), is(notNullValue())); assertThat(ruleSession.getCallerClassName().getName(), is(TestRuleSession.class.getName())); } public static class TestRuleSessionProvider implements SelfDiagnosisRuleProvider { @Override public List<SelfDiagnosisRule> getDefinedRules() { List<SelfDiagnosisRule> ruleList = new ArrayList<>(); ruleList.add(new TestRule1()); ruleList.add(new TestRule2()); ruleList.add(new TestRule3()); return ruleList; } } @SelfDiagnosisRuleDefinition(category="test1",name = "TestRule1") @SelfDiagnosisRuleVisibility.Public public static class TestRule1 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestRule1 has passed."); return result; } } @SelfDiagnosisRuleDefinition(category="test1",name = "TestRule2") @SelfDiagnosisRuleVisibility.LimitedPrivate(acceptedCallers = { TestRuleSession.class }) public static class TestRule2 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestRule2 has passed."); return result; } } @SelfDiagnosisRuleDefinition(category="test1",name = "TestRule3") @SelfDiagnosisRuleVisibility.LimitedPrivate(acceptedCallers = { TestRuleEngine.class }) public static class TestRule3 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestRule3 has passed."); return result; } } protected Path createServiceJar(String className) throws Exception { Path jarPath = new Path(testPath, className+".jar"); Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(new File(jarPath.toUri())), manifest); JarEntry entry = new JarEntry("META-INF/services/"+SelfDiagnosisRuleProvider.class.getName()); jarOut.putNextEntry(entry); jarOut.write(className.getBytes()); jarOut.closeEntry(); jarOut.close(); return jarPath; } protected Path createJarPathForTestRuleSession() throws Exception { return createServiceJar(TestRuleSessionProvider.class.getName()); } @Test public void testGetCandidateRules() throws Exception { ClassLoader parent = Thread.currentThread().getContextClassLoader(); URLClassLoader cl; cl = new URLClassLoader(new URL[] {createJarPathForTestRuleSession().toUri().toURL()}, parent); Thread.currentThread().setContextClassLoader(cl); SelfDiagnosisRuleEngine ruleEngine = SelfDiagnosisRuleEngine.getInstance(); ruleEngine.reset(); SelfDiagnosisRuleSession ruleSession = ruleEngine.newRuleSession(); List<RuleWrapper> candidateRules = ruleSession.withCategoryNames("test1").getCandidateRules(); assertThat(candidateRules, is(notNullValue())); assertThat(candidateRules.size() == 2, is(true)); for (RuleWrapper wrapper: candidateRules) { assertThat(wrapper.getRuleName(), anyOf(is("TestRule1"), is("TestRule2"))); } candidateRules = ruleSession.withRuleNames("TestRule1").getCandidateRules(); assertThat(candidateRules, is(notNullValue())); assertThat(candidateRules.size() == 1, is(true)); for (RuleWrapper wrapper: candidateRules) { assertThat(wrapper.getRuleName(), is("TestRule1")); } try { Method closeMethod = URLClassLoader.class.getMethod("close"); closeMethod.invoke(cl); } catch (NoSuchMethodException ignored) { } } @Test public void testReset() throws Exception { ClassLoader parent = Thread.currentThread().getContextClassLoader(); URLClassLoader cl; cl = new URLClassLoader(new URL[] {createJarPathForTestRuleSession().toUri().toURL()}, parent); Thread.currentThread().setContextClassLoader(cl); SelfDiagnosisRuleEngine ruleEngine = SelfDiagnosisRuleEngine.getInstance(); ruleEngine.reset(); SelfDiagnosisRuleSession ruleSession = ruleEngine.newRuleSession(); List<RuleWrapper> candidateRules = ruleSession.withCategoryNames("test1") .withRuleNames("TestRule1").getCandidateRules(); assertThat(candidateRules, is(notNullValue())); assertThat(candidateRules.size() == 1, is(true)); for (RuleWrapper wrapper: candidateRules) { assertThat(wrapper.getRuleName(), is("TestRule1")); } candidateRules = ruleSession.reset().withCategoryNames("test1").getCandidateRules(); assertThat(candidateRules, is(notNullValue())); assertThat(candidateRules.size() == 2, is(true)); for (RuleWrapper wrapper: candidateRules) { assertThat(wrapper.getRuleName(), anyOf(is("TestRule1"), is("TestRule2"))); } try { Method closeMethod = URLClassLoader.class.getMethod("close"); closeMethod.invoke(cl); } catch (NoSuchMethodException ignored) { } } public static class TestRulePriorityProvider implements SelfDiagnosisRuleProvider { @Override public List<SelfDiagnosisRule> getDefinedRules() { List<SelfDiagnosisRule> ruleList = new ArrayList<>(); ruleList.add(new TestPriorityRule1()); ruleList.add(new TestPriorityRule2()); ruleList.add(new TestPriorityRule3()); ruleList.add(new TestPriorityRule4()); return ruleList; } } @SelfDiagnosisRuleDefinition(category="test2",name = "TestPriorityRule1") @SelfDiagnosisRuleVisibility.Public public static class TestPriorityRule1 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestPriorityRule1 has passed."); return result; } } @SelfDiagnosisRuleDefinition(category="test2",name = "TestPriorityRule2") @SelfDiagnosisRuleVisibility.Public public static class TestPriorityRule2 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestPriorityRule2 has passed."); return result; } } @SelfDiagnosisRuleDefinition(category="test2",name = "TestPriorityRule3",priority=0) @SelfDiagnosisRuleVisibility.Public public static class TestPriorityRule3 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestPriorityRule3 has passed."); return result; } } @SelfDiagnosisRuleDefinition(category="test2",name = "TestPriorityRule4",priority=10) @SelfDiagnosisRuleVisibility.Public public static class TestPriorityRule4 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); result.setReturnCode(EvaluationResultCode.OK); result.setMessage("TestPriorityRule4 has passed."); return result; } } protected Path createJarPathForRulePriority() throws Exception { return createServiceJar(TestRulePriorityProvider.class.getName()); } @Test public void testRulePriority() throws Exception { ClassLoader parent = Thread.currentThread().getContextClassLoader(); URLClassLoader cl; cl = new URLClassLoader(new URL[] {createJarPathForRulePriority().toUri().toURL()}, parent); Thread.currentThread().setContextClassLoader(cl); SelfDiagnosisRuleEngine ruleEngine = SelfDiagnosisRuleEngine.getInstance(); ruleEngine.reset(); SelfDiagnosisRuleSession ruleSession = ruleEngine.newRuleSession(); List<RuleWrapper> candidateRules = ruleSession.withCategoryNames("test2").getCandidateRules(); assertThat(candidateRules, is(notNullValue())); assertThat(candidateRules.size() == 4, is(true)); assertThat(candidateRules.get(0).getRuleName(), is("TestPriorityRule3")); assertThat(candidateRules.get(1).getRuleName(), is("TestPriorityRule4")); candidateRules = ruleSession.withRuleNames("TestPriorityRule1", "TestPriorityRule2", "TestPriorityRule4") .getCandidateRules(); assertThat(candidateRules, is(notNullValue())); assertThat(candidateRules.size() == 3, is(true)); assertThat(candidateRules.get(0).getRuleName(), is("TestPriorityRule4")); try { Method closeMethod = URLClassLoader.class.getMethod("close"); closeMethod.invoke(cl); } catch (NoSuchMethodException ignored) { } } public static class TestExecutionRuleProvider implements SelfDiagnosisRuleProvider { @Override public List<SelfDiagnosisRule> getDefinedRules() { List<SelfDiagnosisRule> ruleList = new ArrayList<>(); ruleList.add(new TestExecRule1()); ruleList.add(new TestExecRule2()); ruleList.add(new TestExecRule3()); return ruleList; } } @SelfDiagnosisRuleDefinition(category="test3",name="TestExecRule1",priority=0) @SelfDiagnosisRuleVisibility.Public public static class TestExecRule1 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); Object rule1_param1 = context.getParameter("TestExecRule1_param1"); try { if (rule1_param1 != null && rule1_param1 instanceof Integer) { int rule1_param1_intVal = Integer.parseInt(rule1_param1.toString()); if (rule1_param1_intVal == 0) { result.setReturnCode(EvaluationResultCode.ERROR); result.setMessage("parameter1 is 0."); } else { result.setReturnCode(EvaluationResultCode.OK); } } else { result.setReturnCode(EvaluationResultCode.ERROR); result.setMessage("parameter1 is null or not a integer type."); } } catch (NumberFormatException e) { result.setReturnCode(EvaluationResultCode.ERROR); result.setMessage(e.getMessage()); result.setThrowable(e); } return result; } } @SelfDiagnosisRuleDefinition(category="test3",name="TestExecRule2",priority=1) @SelfDiagnosisRuleVisibility.Public public static class TestExecRule2 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); Object rule2_param1 = context.getParameter("TestExecRule2_param1"); if (rule2_param1 == null) { result.setReturnCode(EvaluationResultCode.ERROR); result.setMessage("parameter1 is null."); } else { result.setReturnCode(EvaluationResultCode.OK); } return result; } } @SelfDiagnosisRuleDefinition(category="test3",name="TestExecRule3",priority=2) @SelfDiagnosisRuleVisibility.Public public static class TestExecRule3 implements SelfDiagnosisRule { @Override public EvaluationResult evaluate(EvaluationContext context) { EvaluationResult result = new EvaluationResult(); Object rule3_param1 = context.getParameter("TestExecRule3_param1"); if (rule3_param1 != null && rule3_param1 instanceof String) { String rule3_param1_string = (String) rule3_param1; if (rule3_param1_string.startsWith("test")) { result.setReturnCode(EvaluationResultCode.OK); } else { result.setReturnCode(EvaluationResultCode.ERROR); result.setMessage("parameter1 does not start with 'test'."); } } else { result.setReturnCode(EvaluationResultCode.ERROR); result.setMessage("parameter1 is null or not a string type."); } return result; } } protected Path createJarPathForExecutingRules() throws Exception { return createServiceJar(TestExecutionRuleProvider.class.getName()); } @Test public void testFireRules() throws Exception { ClassLoader parent = Thread.currentThread().getContextClassLoader(); URLClassLoader cl; cl = new URLClassLoader(new URL[] {createJarPathForExecutingRules().toUri().toURL()}, parent); Thread.currentThread().setContextClassLoader(cl); SelfDiagnosisRuleEngine ruleEngine = SelfDiagnosisRuleEngine.getInstance(); ruleEngine.reset(); SelfDiagnosisRuleSession ruleSession = ruleEngine.newRuleSession(); EvaluationContext context = new EvaluationContext(); context.addParameter("TestExecRule1_param1", (int)5); context.addParameter("TestExecRule2_param1", "rule2"); context.addParameter("TestExecRule3_param1", "testResult"); ruleSession.withCategoryNames("test3").fireRules(context); try { Method closeMethod = URLClassLoader.class.getMethod("close"); closeMethod.invoke(cl); } catch (NoSuchMethodException ignored) { } } @Test(expected=EvaluationFailedException.class) public void testFireRulesWithException() throws Exception { ClassLoader parent = Thread.currentThread().getContextClassLoader(); URLClassLoader cl; cl = new URLClassLoader(new URL[] {createJarPathForExecutingRules().toUri().toURL()}, parent); Thread.currentThread().setContextClassLoader(cl); SelfDiagnosisRuleEngine ruleEngine = SelfDiagnosisRuleEngine.getInstance(); ruleEngine.reset(); SelfDiagnosisRuleSession ruleSession = ruleEngine.newRuleSession(); EvaluationContext context = new EvaluationContext(); context.addParameter("TestExecRule1_param1", (int)0); context.addParameter("TestExecRule2_param1", "rule2"); context.addParameter("TestExecRule3_param1", "testResult"); try { ruleSession.withCategoryNames("test3").fireRules(context); } finally { try { Method closeMethod = URLClassLoader.class.getMethod("close"); closeMethod.invoke(cl); } catch (NoSuchMethodException ignored) { } } } }