// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed 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 de.ugoe.cs.autoquest.plugin.uml; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.Random; import java.util.Set; import java.util.logging.Level; import static org.junit.Assert.*; import org.eclipse.uml2.uml.Interaction; import org.eclipse.uml2.uml.Model; import org.eclipse.uml2.uml.StateMachine; import org.eclipse.uml2.uml.UMLPackage; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; import de.fraunhofer.fokus.testing.ModelUtils; import de.ugoe.cs.autoquest.eventcore.Event; import de.ugoe.cs.autoquest.plugin.http.HTTPLogParser; import de.ugoe.cs.autoquest.plugin.http.SOAPUtils; import de.ugoe.cs.autoquest.plugin.http.eventcore.SimpleSOAPEventType; import de.ugoe.cs.autoquest.testgeneration.RandomWalkGenerator; import de.ugoe.cs.autoquest.usageprofiles.FirstOrderMarkovModel; import de.ugoe.cs.autoquest.usageprofiles.IStochasticProcess; import de.ugoe.cs.util.SerializationUtils; import de.ugoe.cs.util.console.TextConsole; /** *

* Tests for AutoQUESTs UMLUtils *

* * @author Steffen Herbold */ public class UMLUtilsTest { private final static String OUTPUT_DIR = "target/tmp/test-outputs/"; private final static boolean DELETE_OUTPUTS = false; // for RLUS private final static TestData deda_1 = new TestData("deda_rlus_properties.prop", "deda_usagejournal.log", "deda_rlus_usageprofile.dat", "deda_model.uml", "deda_rlus_model_testsuite.uml", "deda_rlus_model_scheduling.uml"); // for IXS private final static TestData deda_2 = new TestData("deda_ixs_properties.prop", "deda_usagejournal.log", "deda_ixs_usageprofile.dat", "deda_model.uml", "deda_ixs_model_testsuite.uml", "deda_ixs_model_scheduling.uml"); private final static TestData ita_1 = new TestData("ita_properties.prop", "ita_usagejournal.log", "ita_usageprofile.dat", "ita_model.uml", "ita_model_testsuite.uml", "ita_model_scheduling.uml"); private static class TestData { public final String propertiesFile; public final String usageJournalFile; public final String usageProfileFile; public final String dslModelFile; public final String testSuiteFile; public final String schedulingFile; public TestData(String propertiesFile, String usageJournalFile, String usageProfileFile, String dslModelFile, String testSuiteFile, String schedulingFile) { this.propertiesFile = propertiesFile; this.usageJournalFile = usageJournalFile; this.usageProfileFile = usageProfileFile; this.dslModelFile = dslModelFile; this.testSuiteFile = testSuiteFile; this.schedulingFile = schedulingFile; } @Override public String toString() { StringBuilder strBld = new StringBuilder(); strBld.append("Properties " + propertiesFile + "\n"); strBld.append("Usage Journal " + usageJournalFile + "\n"); strBld.append("Usage Profile " + usageProfileFile + "\n"); strBld.append("DSL Model " + dslModelFile + "\n"); strBld.append("Test Suite " + testSuiteFile + "\n"); strBld.append("Scheduling " + schedulingFile + "\n"); return strBld.toString(); } } @BeforeClass public static void setUpBeforeClass() throws Exception { new TextConsole(Level.SEVERE); } @After public void tearDown() throws Exception { if (DELETE_OUTPUTS) { deleteFiles(new File(OUTPUT_DIR)); } } @Test public void testCreateUMLTransitionSequence_ITA_1() throws Exception { TestData testdata = ita_1; /* * Properties properties = loadProperties(testdata); //Collection> sequences = * loadAndPreprocessUsageJournal(testdata, properties); * * Model model = * ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); * * StateMachine stateMachine = (StateMachine) * model.getPackagedElement("StateMachineTransportService", true, * UMLPackage.Literals.STATE_MACHINE, true); * * * Collection> umlSequences = new LinkedList<>(); * * // remove everything but transport from sequences for (List sequence : sequences) * { for (Iterator eventIter = sequence.iterator(); eventIter.hasNext();) { Event * event = eventIter.next(); if * (!"TransportService".equals(SOAPUtils.getServiceNameFromEvent(event))) { * eventIter.remove(); } } umlSequences.add(UMLUtils.createUMLTransitionSequence(sequence, * stateMachine)); } */ Model model = ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); StateMachine stateMachine = (StateMachine) model.getPackagedElement("StateMachineTransportService", true, UMLPackage.Literals.STATE_MACHINE, true); List manuallyCreatedSequence = new LinkedList<>(); manuallyCreatedSequence .add(new Event(new SimpleSOAPEventType("transportInstructionRequest", "TransportService", "Logistics_Environment", null))); manuallyCreatedSequence .add(new Event(new SimpleSOAPEventType("transportInstructionConfirmationRequest", "materialSupplierService", "Logistics_Environment", null))); UMLUtils.createUMLTransitionSequence(manuallyCreatedSequence, stateMachine); } @Test public void testConvertStateMachineToUsageProfile__ITA_1() throws Exception { TestData testdata = ita_1; assertTrue("test currently not working", false); Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); Model model = ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); StateMachine stateMachine = (StateMachine) model.getPackagedElement("StateMachineTransportService", true, UMLPackage.Literals.STATE_MACHINE, true); Collection> umlSequences = new LinkedList<>(); // remove everything but transport from sequences for (List sequence : sequences) { for (Iterator eventIter = sequence.iterator(); eventIter.hasNext();) { Event event = eventIter.next(); if (!"TransportService".equals(SOAPUtils.getServiceNameFromEvent(event))) { eventIter.remove(); } } umlSequences.add(UMLUtils.createUMLTransitionSequence(sequence, stateMachine)); } UMLUtils.convertStateMachineToUsageProfile(umlSequences, stateMachine); ModelUtils.writeModelToFile(model, OUTPUT_DIR + "ita_v2_result.uml"); } @Test public void testCreateInteractionFromEventSequence_DEDA_1() throws Exception { createInteractionFromEventSequenceWorkflow(deda_1); } @Test public void testCreateInteractionFromEventSequence_DEDA_2() throws Exception { createInteractionFromEventSequenceWorkflow(deda_2); } @Test public void testCreateInteractionFromEventSequence_ITA_1() throws Exception { createInteractionFromEventSequenceWorkflow(ita_1); } @Test public void testCalculateUsageScore_DEDA_1() throws Exception { calculateUsageScoreWorkflow(deda_1); } @Test public void testCalculateUsageScore_DEDA_2() throws Exception { calculateUsageScoreWorkflow(deda_2); } @Test public void testCalculateUsageScore_ITA_1() throws Exception { calculateUsageScoreWorkflow(ita_1); } @Test public void testCreateScheduling_DEDA_1() throws Exception { createSchedulingWorkflow(deda_1); } @Test public void testCreateScheduling_DEDA_2() throws Exception { createSchedulingWorkflow(deda_2); } @Test public void testCreateScheduling_ITA() throws Exception { createSchedulingWorkflow(ita_1); } @Test public void testValidateModelWithLog_DEDA_1() throws Exception { validateModelWithLogWorkflow(deda_1); } @Test public void testValidateModelWithLog_DEDA_2() throws Exception { validateModelWithLogWorkflow(deda_2); } @Test public void testValidateModelWithLog_ITA_1() throws Exception { validateModelWithLogWorkflow(ita_1); } private void validateModelWithLogWorkflow(TestData testdata) throws Exception { Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); Model model = ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); // run validation int violations = UMLUtils.validateModelWithLog(sequences, model, properties.getProperty("test.context")); if (violations == 0) { System.out.println("No problems found."); } else { System.out.println(violations + " violations found."); } } private void createInteractionFromEventSequenceWorkflow(TestData testdata) throws Exception { Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); Model model = ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); // create a test case for each observed sequence int i = 0; for (List sequence : sequences) { UMLUtils.createInteractionFromEventSequence(sequence, model, properties.getProperty("testcases.prefix") + "_" + i, properties.getProperty("test.context")); i++; } ModelUtils.writeModelToFile(model, OUTPUT_DIR + testdata.testSuiteFile); } private void calculateUsageScoreWorkflow(TestData testdata) throws Exception { Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); Model model = ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); IStochasticProcess usageProfile = createUsageProfile(testdata, sequences); Collection> generatedSequences = createRandomSequences(usageProfile, properties); int i = 1; List interactions = new LinkedList<>(); int[] lengths = new int[generatedSequences.size()]; for (List sequence : generatedSequences) { interactions.add(UMLUtils .createInteractionFromEventSequence(sequence, model, properties.getProperty("testcases.prefix") + "_" + i, properties.getProperty("test.context"))); lengths[i - 1] = sequence.size(); i++; } for (int j = 0; j < interactions.size(); j++) { double usageScore = UMLUtils.calculateUsageScore(interactions.get(j), usageProfile); System.out.format("usage score %02d: %.2f \t %d\n", j + 1, usageScore, lengths[j]); } } private void createSchedulingWorkflow(TestData testdata) throws Exception { Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); Model model = ModelUtils.loadModel(ClassLoader.getSystemResourceAsStream(testdata.dslModelFile)); IStochasticProcess usageProfile = createUsageProfile(testdata, sequences); Collection> generatedSequences = createRandomSequences(usageProfile, properties); int i = 1; for (List sequence : generatedSequences) { UMLUtils.createInteractionFromEventSequence(sequence, model, properties.getProperty("testcases.prefix") + "_" + i, properties.getProperty("test.context")); i++; } UMLUtils.createScheduling(model, usageProfile, properties.getProperty("test.context")); ModelUtils.writeModelToFile(model, OUTPUT_DIR + testdata.schedulingFile); } private Properties loadProperties(TestData testdata) throws Exception { Properties properties = new Properties(); properties.load(new FileInputStream(ClassLoader.getSystemResource(testdata.propertiesFile) .getFile())); return properties; } private Collection> loadAndPreprocessUsageJournal(TestData testdata, Properties properties) throws Exception { // load usage journal HTTPLogParser parser = new HTTPLogParser(new File(ClassLoader.getSystemResource(testdata.propertiesFile) .getFile())); parser.parseFile(new File(ClassLoader.getSystemResource(testdata.usageJournalFile) .getFile())); Collection> sequences = parser.getSequences(); // remove non SOAP events and convert to SimpleSOAPEventType Collection> simpleSOAPSequences = new LinkedList<>(); for (List sequence : sequences) { simpleSOAPSequences.add(SOAPUtils.convertToSimpleSOAPEvent(sequence, true)); } // remove calls to ingored services Set ignoredServices = new HashSet<>(); String ignoredServicesString = properties.getProperty("test.ignored.services"); if (ignoredServicesString != null) { for (String service : ignoredServicesString.split(",")) { ignoredServices.add(service.trim()); } } for (List sequence : simpleSOAPSequences) { for (Iterator eventIter = sequence.iterator(); eventIter.hasNext();) { Event event = eventIter.next(); SimpleSOAPEventType eventType = (SimpleSOAPEventType) event.getType(); if (ignoredServices.contains(eventType.getServiceName())) { eventIter.remove(); } } } return simpleSOAPSequences; } private IStochasticProcess createUsageProfile(TestData testdata, Collection> sequences) throws Exception { FirstOrderMarkovModel usageProfile = new FirstOrderMarkovModel(new Random(1)); usageProfile.train(sequences); FileOutputStream fos = new FileOutputStream(OUTPUT_DIR + testdata.usageProfileFile); SerializationUtils.serialize(usageProfile, fos); fos.close(); return usageProfile; } private Collection> createRandomSequences(IStochasticProcess usageProfile, Properties properties) throws Exception { int numberOfTestCases = Integer.parseInt(properties.getProperty("testcases.number")); int testCaseMinLength = Integer.parseInt(properties.getProperty("testcases.minlenth", "1")); int testCaseMaxLength = Integer.parseInt(properties.getProperty("testcases.maxlenth", "100")); int maxIter = numberOfTestCases * 100; RandomWalkGenerator testGenerator = new RandomWalkGenerator(numberOfTestCases, testCaseMinLength, testCaseMaxLength, true, maxIter); return testGenerator.generateTestSuite(usageProfile); } private void deleteFiles(File file) { if (file.exists()) { if (file.isDirectory()) { for (File child : file.listFiles()) { deleteFiles(child); } } try { file.delete(); } catch (Exception e) { // ignore and delete as much as possible } } } }