// 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);
}
@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
int i = 0;
for (List sequence : sequences) {
UMLUtils.createInteractionFromEventSequence(sequence, model,
properties.getProperty("testcases.prefix") +
"_" + i,
properties.getProperty("test.context"),
false);
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(new File(ClassLoader.getSystemResource(testdata.dslModelFile)
.getFile()));
IStochasticProcess usageProfile = createUsageProfile(testdata, properties, 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"),
Boolean.parseBoolean(properties.getProperty("testcases.data.random", "false"))));
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);
int i = 1;
for (List sequence : generatedSequences) {
UMLUtils.createInteractionFromEventSequence(sequence, model,
properties.getProperty("testcases.prefix") +
"_" + i,
properties.getProperty("test.context"),
true);
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();
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.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
}
}
}
}