// 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.LinkedList; import java.util.List; import java.util.Properties; import java.util.Random; 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.HighOrderMarkovModel; import de.ugoe.cs.autoquest.usageprofiles.IStochasticProcess; import de.ugoe.cs.autoquest.usageprofiles.TrieBasedModel; 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_imported_properties.prop", "ita_imported_usagejournal.log", "ita_imported_usageprofile.dat", "ita_imported_model.uml", "ita_imported_model_testsuite.uml", "ita_imported_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.FINE); File outdir = new File(OUTPUT_DIR); if( !outdir.exists() ) { outdir.mkdirs(); } } @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(new * File(ClassLoader.getSystemResource(testdata.dslModelFile).getFile())); * * 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(new File(ClassLoader.getSystemResource(testdata.dslModelFile) .getFile())); 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, null, null))); manuallyCreatedSequence .add(new Event(new SimpleSOAPEventType("transportInstructionConfirmationRequest", "materialSupplierService", "Logistics_Environment", null, null, null))); // TODO make test case run // UMLUtils.createUMLTransitionSequence(manuallyCreatedSequence, stateMachine); } @Test public void testConvertStateMachineToUsageProfile__ITA_1() throws Exception { // TODO make test run /* * 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_1() 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); } @Test public void testSerialization_ITA_1() throws Exception { TestData testdata = ita_1; Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); IStochasticProcess model = createUsageProfile(testdata, properties, sequences); byte[] serialized = SerializationUtils.serialize(model); SerializationUtils.deserialize(serialized); } private void validateModelWithLogWorkflow(TestData testdata) throws Exception { Properties properties = loadProperties(testdata); Collection> sequences = loadAndPreprocessUsageJournal(testdata, properties); Model model = ModelUtils.loadModel(new File(ClassLoader.getSystemResource(testdata.dslModelFile) .getFile())); // 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(new File(ClassLoader.getSystemResource(testdata.dslModelFile) .getFile())); // create a test case for each observed sequence UMLUtils.createInteractionFromEventSequence(sequences, model, properties.getProperty("testcases.prefix"), properties.getProperty("test.context"), false); 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(new File(ClassLoader.getSystemResource(testdata.dslModelFile) .getFile())); IStochasticProcess usageProfile = createUsageProfile(testdata, properties, sequences); Collection> generatedSequences = createRandomSequences(usageProfile, properties); int i = 1; List interactions = UMLUtils.createInteractionFromEventSequence(generatedSequences, model, properties.getProperty("testcases.prefix"), properties.getProperty("test.context"), Boolean.parseBoolean(properties.getProperty("testcases.data.random", "false"))); int[] lengths = new int[generatedSequences.size()]; for (List sequence : generatedSequences) { 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(new File(ClassLoader.getSystemResource(testdata.dslModelFile) .getFile())); IStochasticProcess usageProfile = createUsageProfile(testdata, properties, sequences); Collection> generatedSequences = createRandomSequences(usageProfile, properties); UMLUtils.createInteractionFromEventSequence(generatedSequences, model, properties.getProperty("testcases.prefix"), properties.getProperty("test.context"), Boolean.parseBoolean(properties.getProperty("testcases.data.random", "false"))); 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(); sequences = SOAPUtils.removeNonSOAPEvents(sequences); sequences = SOAPUtils.sortAndConvertSequences(sequences, true, true); sequences = SOAPUtils.normalizeOperationNames(sequences, properties .getProperty("methodName.prefixToRemove"), properties .getProperty("methodName.suffixToRemove")); sequences = SOAPUtils.removeCallsToIgnoredServices(sequences, properties.getProperty("test.ignored.services")); return sequences; } private IStochasticProcess createUsageProfile(TestData testdata, Properties properties, Collection> sequences) throws Exception { TrieBasedModel usageProfile = new HighOrderMarkovModel(Integer.parseInt(properties.getProperty("usageprofile.markovorder", "1")), 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.minlength", "1")); long maxIterValidSequence = Long.parseLong(properties.getProperty("testcases.maxIterValid", "100")); int testCaseMaxLength = Integer.parseInt(properties.getProperty("testcases.maxlength", "100")); int maxIter = numberOfTestCases * 100; RandomWalkGenerator testGenerator = new RandomWalkGenerator(numberOfTestCases, testCaseMinLength, testCaseMaxLength, true, maxIter, maxIterValidSequence); return SOAPUtils.dropInvalidResponseRequestPairs(testGenerator.generateTestSuite(usageProfile)); } private void deleteFiles(File file) { if (file.exists()) { if (file.isDirectory()) { File[] children = file.listFiles(); if (children != null) { for (File child : children) { deleteFiles(child); } } } try { file.delete(); } catch (Exception e) { // ignore and delete as much as possible } } } }