diff --git a/burt-quality-checker/src/main/java/sealab/burt/qualitychecker/JSONGraphReader.java b/burt-quality-checker/src/main/java/sealab/burt/qualitychecker/JSONGraphReader.java index bade28062..ca96f904e 100644 --- a/burt-quality-checker/src/main/java/sealab/burt/qualitychecker/JSONGraphReader.java +++ b/burt-quality-checker/src/main/java/sealab/burt/qualitychecker/JSONGraphReader.java @@ -22,7 +22,10 @@ import sealab.burt.qualitychecker.graph.db.GraphGenerator; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -72,17 +75,14 @@ public static void readGraph(String appName, String appVersion) throws Exception String.join("-", packageName, appVersion)).toString(); String key = getKey(appName, appVersion); -// log.debug("Reading graph from JSON files for " + key); + log.debug("Reading graph from JSON files for " + key); List crashScopeExecutions = readExecutions(dataLocation); GraphGenerator generator = new GraphGenerator(); - // changed code: check if crashScopeExecutions is empty + // check if crashScopeExecutions is empty if (!crashScopeExecutions.isEmpty()) { App app = crashScopeExecutions.get(0).getApp(); - - //---------------------------------------- - generator.generateGraph(crashScopeExecutions, app, GraphDataSource.CS); } @@ -144,27 +144,21 @@ private static void checkScreenshots(AppGraphInfo graphInfo) { private static List readExecutions(String dataLocation) throws Exception { - //-------------------------- -// List executionFiles = Files.find(Paths.get(dataLocation), 1, -// (path, attr) -> path.toFile().getName().startsWith("Execution-")) -// .collect(Collectors.toList()); - //------ changed code: check if the path exists---------------// + //------ check if the path exists---------------// List executionFiles = new ArrayList<>(); - File folder = new File(String.valueOf(Paths.get(dataLocation))); - if (folder.exists() && folder.isDirectory()){ + File folder = new File(dataLocation); + if (folder.exists()){ executionFiles = Files.find(Paths.get(dataLocation), 1, (path, attr) -> path.toFile().getName().startsWith("Execution-")) .collect(Collectors.toList()); } - //------ new code: check if the path exists---------------// + //------ check if the path exists---------------// if (executionFiles.isEmpty()) -// throw new RuntimeException("There are no execution files in " + dataLocation); log.debug("There are no execution files in " + dataLocation); log.debug("Reading execution data from : " + executionFiles); - //---------------------- List executions = new ArrayList<>(); Long componentId = 0L; @@ -174,9 +168,11 @@ private static List readExecutions(String dataLocation) throws Except for (int i = 0; i < executionFiles.size(); i++) { Path executionFile = executionFiles.get(i); - //Set up a new Gson object - JsonReader reader = new JsonReader(new FileReader(executionFile.toFile())); +// JsonReader reader = new JsonReader(new FileReader(executionFile.toFile())); + JsonReader reader = new JsonReader(new InputStreamReader( + new FileInputStream(executionFile.toFile()), StandardCharsets.UTF_8 + )); // De-serialize the Execution object. Execution execution = gson.fromJson(reader, Execution.class); diff --git a/burt-server/pom.xml b/burt-server/pom.xml index 58a537a67..e06ea15c6 100644 --- a/burt-server/pom.xml +++ b/burt-server/pom.xml @@ -21,7 +21,7 @@ org.springframework.boot spring-boot-starter - + ` org.springframework.boot spring-boot-devtools diff --git a/burt-server/src/main/java/sealab/burt/server/output/HTMLBugReportGenerator.java b/burt-server/src/main/java/sealab/burt/server/output/HTMLBugReportGenerator.java index 8f89d8e2f..d9ffcdcbf 100644 --- a/burt-server/src/main/java/sealab/burt/server/output/HTMLBugReportGenerator.java +++ b/burt-server/src/main/java/sealab/burt/server/output/HTMLBugReportGenerator.java @@ -12,6 +12,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.List; @@ -25,7 +26,7 @@ class HTMLBugReportGenerator { public void generateOutput(File outputFile, ConversationState state) throws Exception { File htmlTemplate = new File(Path.of(".", "example", "template.html").toString()); String finalReport = generateHTML(htmlTemplate, state); - FileUtils.write(outputFile, finalReport, Charset.defaultCharset()); + FileUtils.write(outputFile, finalReport, StandardCharsets.UTF_8); bugReportId++; } diff --git a/burt-tools/pom.xml b/burt-tools/pom.xml index 1bd3b8a57..67a4d83e0 100644 --- a/burt-tools/pom.xml +++ b/burt-tools/pom.xml @@ -7,13 +7,10 @@ sealab.burt burt-tools 0.0.1 - burt-tools BURTs miscellaneous tools - - 11 - 11 + 11 @@ -24,18 +21,53 @@ compile - Android-Core - Android-Core - 1.0 - compile - - - - xml-apis - xml-apis - - + org.projectlombok + lombok + 1.18.18 + provided + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + dependency + + class + + + + + + + + \ No newline at end of file diff --git a/burt-tools/run_graph_generation.bat b/burt-tools/run_graph_generation.bat new file mode 100644 index 000000000..883b7e0a0 --- /dev/null +++ b/burt-tools/run_graph_generation.bat @@ -0,0 +1,11 @@ + +set CUR_DIR=%CD% + +cd ..\burt-nlparser && call mvn clean install -DskipTests && @echo on +cd ..\burt-quality-checker && call mvn clean install -DskipTests && @echo on + +cd "%CUR_DIR%" + +call mvn package -DskipTests +REM call java -Dfile.encoding=UTF-8 -cp target\burt-tools-0.0.1.jar MainJSONGraphGenerator +call java -cp target\burt-tools-0.0.1.jar MainJSONGraphGenerator \ No newline at end of file diff --git a/burt-tools/run_graph_generation.sh b/burt-tools/run_graph_generation.sh new file mode 100644 index 000000000..6c41fda4a --- /dev/null +++ b/burt-tools/run_graph_generation.sh @@ -0,0 +1,12 @@ +export CUR_DIR=`pwd` + + +cd $CUR_DIR + +cd ../burt-nlparser && mvn clean install -DskipTests +#cd ../crashscope && mvn clean install -DskipTests +cd ../burt-quality-checker && mvn clean install -DskipTests +cd $CUR_DIR + +mvn package -DskipTests +java -cp target/burt-tools-0.0.1.jar MainJSONGraphGenerator \ No newline at end of file diff --git a/burt-tools/src/main/java/DBUtils.java b/burt-tools/src/main/java/DBUtils.java deleted file mode 100644 index 9c9370f52..000000000 --- a/burt-tools/src/main/java/DBUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -import edu.semeru.android.core.entity.model.fusion.Execution; -import edu.semeru.android.core.entity.model.fusion.Step; -import edu.semeru.android.core.helpers.device.DeviceHelper; -import edu.semeru.android.core.service.PersistDataService; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; -import java.util.HashMap; - -public class DBUtils { - - public static final String DEFAULT_EM = "CrashScope-Bug-Reporoduction"; - - public static EntityManager createEntityManager() { - return createEntityManager(DEFAULT_EM); - } - - public static EntityManager createEntityManager(String dbEntityManager) { - EntityManagerFactory emf = Persistence.createEntityManagerFactory(dbEntityManager); - return emf.createEntityManager(); - } - - public static Execution getExecution(String executionName) { - Execution execution = PersistDataService.getExecutionByExecutionType(executionName, DEFAULT_EM, - new HashMap()); - if (execution == null) { - execution = new Execution(); - execution.setExecutionType(executionName); - } - return execution; - } - - public static Step getOpenAppStep(String packageName, Execution execution, int sequence) { - Step openApp = new Step(); - openApp.setAction(DeviceHelper.OPEN_APP); - openApp.setExecution(execution); - openApp.setTextEntry(packageName); - openApp.setSequenceStep(sequence); - return openApp; - } -} diff --git a/burt-tools/src/main/java/DeviceUtils.java b/burt-tools/src/main/java/DeviceUtils.java deleted file mode 100644 index 345ab102a..000000000 --- a/burt-tools/src/main/java/DeviceUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -import edu.semeru.android.core.helpers.device.DeviceHelper; -import seers.appcore.utils.JavaUtils; - -import java.util.Set; - -public class DeviceUtils { - - public static boolean isSwipe(Integer event) { - return event == DeviceHelper.SWIPE_DOWN || event == DeviceHelper.SWIPE_LEFT || event == DeviceHelper.SWIPE_RIGHT - || event == DeviceHelper.SWIPE_UP; - } - - public static boolean isClick(Integer event) { - return DeviceHelper.LONG_CLICK == event || DeviceHelper.CLICK == event; - } - - public static boolean isType(Integer event) { - return DeviceHelper.TYPE == event; - } - - public static boolean isAnyInputType(Integer event) { - return DeviceHelper.TYPE == event || DeviceHelper.CLICK_TYPE == event; - } - - public static boolean isDeleteText(Integer event) { - return DeviceHelper.DELETE_TEXT == event; - } - - public static boolean isAnyType(Integer event) { - return isType(event) || isDeleteText(event); - } - - public static boolean isOpenApp(Integer event) { - return DeviceHelper.OPEN_APP == event; - } - - public static boolean isNothing(Integer event) { - return DeviceHelper.NOTHING == event; - } - - public static boolean isClickBackButton(Integer event) { - return DeviceHelper.BACK == event; - } - - public static boolean isClickMenuButton(Integer event) { - return DeviceHelper.MENU_BTN == event; - } - - public static boolean isKeyEvent(Integer event) { - return DeviceHelper.KEYEVENT == event; - } - - public static boolean isChangeRotation(Integer event) { - return DeviceHelper.ROTATION == event; - } - - public static Set SPECIAL_CHARS = JavaUtils.getSet( "%", "'", "(", ")", "&", "<", ">", ";", "*", "|", - "~", "¬", "`", "$"); - - public static String encodeText(String text) { - if (text == null) return null; - StringBuilder builder = new StringBuilder(text.replace(" ", "%s").replace("\\", "\\\\").replace("\"", - "\\\"")); - SPECIAL_CHARS.stream().forEach(c -> { - int i = builder.indexOf(c); - if (i != -1) - builder.insert(i, '\\'); - }); - return builder.toString(); - } - -} diff --git a/burt-tools/src/main/java/GraphGenerator.java b/burt-tools/src/main/java/GraphGenerator.java deleted file mode 100644 index 3c5e24343..000000000 --- a/burt-tools/src/main/java/GraphGenerator.java +++ /dev/null @@ -1,706 +0,0 @@ -import edu.semeru.android.core.dao.AppDao; -import edu.semeru.android.core.entity.model.App; -import edu.semeru.android.core.entity.model.fusion.DynGuiComponent; -import edu.semeru.android.core.entity.model.fusion.Execution; -import edu.semeru.android.core.entity.model.fusion.Screen; -import edu.semeru.android.core.entity.model.fusion.Step; -import edu.semeru.android.core.helpers.device.DeviceHelper; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.xml.sax.InputSource; -import sealab.burt.nlparser.euler.actions.utils.GeneralUtils; -import sealab.burt.qualitychecker.graph.*; - -import javax.persistence.EntityManager; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.ByteArrayInputStream; -import java.io.StringWriter; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * {Insert class description here} - * - * @author Carlos Bernal - */ -public class GraphGenerator { - - private static final Logger LOGGER = LoggerFactory.getLogger(GraphGenerator.class); - - private HashMap states; - private HashMap transitions; - - public GraphGenerator() { - states = new LinkedHashMap<>(); - transitions = new LinkedHashMap<>(); - } - - public AppGraphInfo generateGraph(EntityManager em, Long idApp) throws Exception { - - AppDao appDao = new AppDao(); - App app = appDao.getById(idApp, em); - if (app != null) { - return generateGraph(app); - } - - return null; - } - - public AppGraphInfo generateGraph(EntityManager em, String packageApp, String version) throws Exception { - AppDao appDao = new AppDao(); - App app = appDao.getUniqueByPackage(packageApp, version, em); - if (app != null) { - return generateGraph(app); - } - return null; - } - - public AppGraphInfo generateGraph(App app) throws Exception { - - states.clear(); - transitions.clear(); - - List allSteps = new ArrayList<>(); - for (Execution execution : app.getExecutions()) { - // if (execution.getId() == 9) { - try { - if (!execution.getSteps().isEmpty()) { - List steps = processExecution(execution); - allSteps.addAll(steps); - // System.out.println("=="+execution.getSteps().size()+"=="); - // System.out.println("===================="); - } - } catch (Exception e) { - LOGGER.error("Error for execution " + execution.getId(), e); - throw e; - } - // } - } - - AppGraph graph = buildDirectedGraph(); - - AppGraphInfo graphInfo = new AppGraphInfo(); - graphInfo.setGraph(graph); - graphInfo.setSteps(allSteps); - graphInfo.setApp(Transform.getAppl(app)); - - return graphInfo; - } - - public AppGraph buildDirectedGraph() { - - AppGraph directedGraph = new AppGraph<>(GraphTransition.class); - - getStates().forEach((k, s) -> { - boolean added = directedGraph.addVertex(s); - if (!added) { - LOGGER.warn("Vertex not added: " + s); - } - }); - - getTransitions().forEach((k, t) -> { - boolean added = directedGraph.addEdge(t.getSourceState(), t.getTargetState(), t); - if (!added) { - LOGGER.warn("Edge not added: " + t); - } - }); - - return directedGraph; - } - - private List processExecution(Execution execution) throws Exception { - return updateGraph(execution.getId(), execution.getSteps(), true, GraphState.END_STATE); - } - - public List updateGraph(Long executionId, List steps, boolean addOpenApp, GraphState endState) - throws Exception { - - List appSteps = new ArrayList<>(); - - //no steps - if (steps == null || steps.isEmpty()) { - return appSteps; - } - - // ------------------------------------------- - //filter out the 'nothing' and 'open app' events - - steps = steps.stream() - .filter(step -> !DeviceUtils.isNothing(step.getAction()) && !DeviceUtils.isOpenApp(step.getAction())) - .collect(Collectors.toList()); - - //no steps - if (steps.isEmpty()) { - return appSteps; - } - - // ------------------------------------------- - HashMap> stepScreens = new HashMap<>(); - - GraphState firstState = null; - for (int i = 0; i < steps.size() - 1; i++) { - - Step previousStep = null; - if (i > 0) { - previousStep = steps.get(i - 1); - } - final Step step = steps.get(i); - final Step nextStep = steps.get(i + 1); - final Long executionId1 = executionId != null ? executionId : step.getExecution().getId(); - final int stepAction = step.getAction(); - - //---------------------------------------- - - Screen sourceScreen = step.getScreen(); - Screen tgtScreen = nextStep.getScreen(); - - //---------------------------------------- - boolean skip = false; - - //no src/tgt screens - if (sourceScreen == null && tgtScreen == null) { - skip = true; - } else if (sourceScreen == null) { - //set the same screen of the previous step to "back" steps - if ((DeviceUtils.isClickBackButton(stepAction)|| - DeviceUtils.isAnyType(stepAction) || DeviceHelper.CLICK_TYPE == stepAction) - && previousStep != null) { - final ImmutablePair screenPair = stepScreens.get(previousStep.getId()); - //only if the previous step has a screen - if (screenPair != null) { - stepScreens.put(step.getId(), screenPair); - sourceScreen = screenPair.left; - step.setScreen(sourceScreen); - } else { - skip = true; - } - } else { - skip = true; - } - } else if (tgtScreen == null) { - //assume that types lead to the same screen, i.e., src screen == tgt screen - if (DeviceUtils.isAnyType(stepAction) || DeviceHelper.CLICK_TYPE == stepAction) { - tgtScreen = sourceScreen; - nextStep.setScreen(tgtScreen); - } else { - skip = true; - } - } - - if (skip) { - LOGGER.warn(String.format("Skipping step %s-%s-%s, no src and/or tgt screens, " + - "action: (%s) %s", - executionId1, step.getId(), step.getSequenceStep(), stepAction, - GeneralUtils.getEventName(stepAction))); - continue; - } - - - //---------------------------------------- - //add states and transition - - GraphState sourceState = getStepState(step, stepScreens, sourceScreen); - GraphState targetState = getStepState(nextStep, stepScreens, tgtScreen); - - addGraphTransition(executionId1, appSteps, sourceState, targetState, step); - - //---------------------------------------- - //save the first state - - if (firstState == null) { - firstState = sourceState; - } - } - - //---------------------------------------- - - //add last step - - Step previousStep = null; - if (steps.size() > 1) { - previousStep = steps.get(steps.size() - 2); - } - Step step = steps.get(steps.size() - 1); - - Integer stepAction = step.getAction(); - Screen sourceScreen = step.getScreen(); - final Long executionId1 = executionId != null ? executionId : step.getExecution().getId(); - - boolean skip = false; - if (endState == null) { - skip = true; - } else if (sourceScreen == null) { - if (!DeviceUtils.isClickBackButton(stepAction) || previousStep == null) { - skip = true; - } else { - final ImmutablePair screenPair = stepScreens.get(previousStep.getId()); - if (screenPair != null) { - stepScreens.put(step.getId(), screenPair); - sourceScreen = screenPair.left; - step.setScreen(sourceScreen); - } else { - skip = true; - } - } - } - - if (skip) { - LOGGER.warn(String.format("Skipping last step %s-%s-%s, no src and/or tgt screens, " + - "action: (%s) %s", - executionId1, step.getId(), step.getSequenceStep(), step.getAction(), - GeneralUtils.getEventName(step.getAction()))); - } else { - states.putIfAbsent(endState.getUniqueHash(), endState); - GraphState sourceState = getStepState(step, stepScreens, sourceScreen); - addGraphTransition(executionId1, appSteps, sourceState, endState, step); - - if (firstState == null) { - firstState = sourceState; - } - } - - // --------------------------------------------------- - - //add "open app" step - - if (addOpenApp && firstState != null) { - GraphState sourceState = GraphState.START_STATE; - states.put(sourceState.getUniqueHash(), sourceState); - - Step startAppStep = new Step(); - startAppStep.setAction(DeviceHelper.OPEN_APP); - startAppStep.setSequenceStep(0); - - final long executionId2 = executionId != null ? executionId : 0L; - addGraphTransition(executionId2, appSteps, sourceState, firstState, startAppStep); - } - - // --------------------------------------------------- - - return appSteps; - } - - private GraphState getStepState(Step step, HashMap> stepScreens, - Screen screen) { - final ImmutablePair screenPair = stepScreens.get(step.getId()); - if (screenPair != null) - return screenPair.right; - - final GraphState graphState = addGraphState(screen); - stepScreens.put(step.getId(), new ImmutablePair<>(screen, graphState)); - return graphState; - } - - public GraphState addGraphState(Screen screen) { - List screenComponents = screen.getDynGuiComponents(); - -// HierarchyNode node = getUniqueState2(screenComponents); - - DynGuiComponent root = findRootComponent(screenComponents); - StringBuilder builder = getUniqueState(root); - int hashCode = builder.toString().hashCode(); - - // StringBuilder builder = getUniqueState(screenComponents); - // int hashCode = builder.toString().hashCode(); - - // System.out.print(stateName); - GraphState currentState; - // Get state from the map - if (states.containsKey(hashCode)) { - // System.out.println(" found " + - // states.get(hashCode).getName()); - currentState = states.get(hashCode); - } else { - // Get the GraphSate node - currentState = getGraphState(screen, hashCode); - - // System.out.println("S - " + newState.toString() + ": " + - // builder.toString()); - states.put(hashCode, currentState); - } - return currentState; - } - - private void addGraphTransition(Long executionId, List appSteps, GraphState sourceState, - GraphState targetState, Step step) throws Exception { - - // System.out.print("Step #" + executionId + "-" + - // previousStep.getSequenceStep()); - - // ----------------------------------- - - // Set component that triggered the action - AppGuiComponent component = Transform.getGuiComponent(step.getDynGuiComponent(), null); - - // Transform a Step to AppStep - List newAppSteps = getAppSteps(executionId, step, component); - for (AppStep appStep : newAppSteps) { - - appStep.setCurrentState(sourceState); - // Create transition attached to any AppStep - GraphTransition transition = getGraphTransition(sourceState, targetState, appStep); - // Add relationship - appStep.setTransition(transition); - appSteps.add(appStep); - - } - } - - /** - * @param sourceState - * @param targetState - * @param appStep - * @return - */ - private GraphTransition getGraphTransition(GraphState sourceState, GraphState targetState, AppStep appStep) { - // ---------------------------------- - - String hashTransition = getTransitionHash(sourceState, targetState, appStep); - - // System.out.print(hashTransition); - GraphTransition transition = null; - if (transitions.containsKey(hashTransition)) { - transition = transitions.get(hashTransition); - // System.out.println(" found " + transition.getUniqueHash()); - } else { - transition = getGraphTransition(sourceState, targetState, appStep, hashTransition); - transitions.put(hashTransition, transition); - } - // System.out.println("T - " + transition.getId() + ": " + - // transition.getName()); - return transition; - } - - /** - * @param sourceState - * @param targetState - * @param appStep - * @param hashTransition - * @return - */ - private GraphTransition getGraphTransition(GraphState sourceState, GraphState targetState, AppStep - appStep, String hashTransition) { - GraphTransition transition; - // Create a new transition - transition = new GraphTransition(); - transition.setId(hashTransition.hashCode()); - transition.setSourceState(sourceState); - transition.setTargetState(targetState); - transition.setName(getTransitionName(appStep, sourceState, targetState)); - transition.setUniqueHash(hashTransition); - transition.setStep(appStep); - return transition; - } - - public List getAppSteps(Step step) { - AppGuiComponent component = Transform.getGuiComponent(step.getDynGuiComponent(), null); - return getAppSteps(step.getExecution().getId(), step, component); - - } - - private List getAppSteps(Long executionId, Step step, AppGuiComponent component) { - List appSteps = new ArrayList<>(); - - final int stepAction = step.getAction(); - - if (DeviceHelper.CLICK_TYPE == stepAction) { -// appSteps.add(getNewStep(executionId, previousStep, component, DeviceHelper.CLICK)); - appSteps.add(getNewStep(executionId, step, component, DeviceHelper.TYPE)); - } else { - appSteps.add(getNewStep(executionId, step, component, stepAction)); - } - - return appSteps; - } - - private AppStep getNewStep(Long executionId, Step previousStep, AppGuiComponent component, int stepAction) { - AppStep appStep = new AppStep(); - appStep.setAction(stepAction); - appStep.setComponent(component); - appStep.setExecution(executionId); - appStep.setSequence(previousStep.getSequenceStep()); - appStep.setText(getStepText(previousStep)); - appStep.setException(previousStep.getExceptions()); - appStep.setScreenshotFile(previousStep.getScreenshot()); - appStep.setId(previousStep.getId()); - return appStep; - } - - private String getTransitionHash(GraphState currentState, GraphState newState, AppStep appStep) { - return currentState.getUniqueHash() + ":" + newState.getUniqueHash() + ":" + appStep.getUniqueHash(); - } - - private String getTransitionName(AppStep appStep, GraphState srcState, GraphState tgtState) { - return String.format("(s:%s,t:%s): %s", - srcState.getUniqueHash(), - tgtState.getUniqueHash(), - appStep.toString()); - } - - private String getStepText(Step step) { - - if (step.getAction() == DeviceHelper.TYPE) { - String textEntry = step.getTextEntry(); - Pattern p = Pattern.compile("(?s).+shell input text (.+)"); - Matcher m = p.matcher(textEntry); - if (m.matches()) { - return m.group(1); - } - } - return ""; - } - - private String getFormattedXml(String xml) throws Exception { - - // Turn xml string into a document - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder() - .parse(new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")))); - - Transformer transformer = TransformerFactory.newInstance().newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - - // initialize StreamResult with File object to save to file - StringWriter stringWriter = new StringWriter(); - transformer.transform(new DOMSource(document), new StreamResult(stringWriter)); - return stringWriter.toString(); - } - - private String getStateName(DynGuiComponent dynGuiComponent, int hashCode) { - String stateName; - if (dynGuiComponent != null) { - String[] activityTokens = dynGuiComponent.getActivity().split("\\."); - String suffix = activityTokens[activityTokens.length - 1]; - - stateName = hashCode + ", " + suffix; - } else { - stateName = hashCode + ""; - } - return stateName; - } - - public GraphState getGraphState(Screen screen, int pHashCode) { - List components = screen.getDynGuiComponents(); - - DynGuiComponent root = findRootComponent(components); -// HierarchyNode node = getUniqueState2(components); - StringBuilder builder = getUniqueState(root); - // Don't recompute the hashCode if it is -1 - int hashCode = pHashCode == -1 ? builder.toString().hashCode() : pHashCode; - - final DynGuiComponent firstComponent = root.getChildren().get(0); - String stateName = getStateName(firstComponent, hashCode); - - // Create a new state - GraphState currentState = new GraphState(); - currentState.setUniqueHash(hashCode); - currentState.setName(stateName); - currentState.setScreenId(screen.getId()); - - // Transform components - final List guiComponents = Transform.getGuiComponents(components); - currentState.setComponents(guiComponents); - - String xml = builder.toString(); - try { - currentState.setUnformattedXml(xml); -// currentState.setFormattedXml(getFormattedXml(xml)); - } catch (Exception e) { - LOGGER.error("XML error for screen " + screen.getId() + ": " + xml); - throw e; - } - return currentState; - } - - private DynGuiComponent findRootComponent(List components) { - final Optional compOpt = components.stream().filter(c -> c.getParent() == null && "NO_ID" - .equals(c.getIdXml())).findFirst(); - - if (compOpt.isPresent()) - return compOpt.get(); - - return null; - - } - - - /*private HierarchyNode getUniqueState2(List components) { - - // Find root node - DynGuiComponent root = findRootComponent(components); - if (root == null) return null; - HierarchyNode node = visitComponents2(root); - - return node; - } - - - private HierarchyNode visitComponents2(DynGuiComponent comp) { - - - List childrenSet = new ArrayList<>(); - for (DynGuiComponent child : comp.getChildren()) { - HierarchyNode childNode = visitComponents2(child); - childrenSet.add(childNode); - } - - HierarchyNode node = new HierarchyNode(comp, childrenSet); - - return node; - - } - - public static class HierarchyNode { - - DynGuiComponent component; - List children; - - public HierarchyNode(DynGuiComponent component, List children) { - super(); - this.component = component; - this.children = children; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((children == null) ? 0 : children.hashCode()); - result = prime * result + ((component == null) ? 0 : component.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - HierarchyNode other = (HierarchyNode) obj; - if (children == null) { - if (other.children != null) - return false; - } else if (!children.equals(other.children)) - return false; - if (component == null) { - if (other.component != null) - return false; - } else if (!component.equals(other.component)) - return false; - return true; - } - - @Override - public String toString() { - return "HierarchyNode [comp=" + component + ", children=" + children + "]"; - } - - }*/ - - /** - * Gives a unique screen based on the hierarchy - * - * @param root - * @return - */ - private StringBuilder getUniqueState(DynGuiComponent root) { - - StringBuilder builder = new StringBuilder(); - - final DynGuiComponent firstComponent = root.getChildren().get(0); - builder.append(String.format("%s%s", - firstComponent.getWidth(), firstComponent.getHeight())); - builder.append(String.format("%s%s", - firstComponent.getPositionX(), firstComponent.getPositionY())); - - - visitComponents(root, builder); - - // System.out.println(builder.toString()); - // System.out.println("----------------------------"); - - return builder; - } - - /** - * This method generates an string with the hierarchy of the screen just - * considering the type of the component. Most likely we will play with this - * method to change the number of states we will generate in the final graph - * - * @param component - * @param builder - */ - private void visitComponents(DynGuiComponent component, StringBuilder builder) { -// String elementName = getXmlElementName(component.getName()); -// String elementName = component.getName(); - - String elementName = String.join("_", component.getName(), component.getIdXml().replace("id/", ""), - //UiAutoConnector.getTextcomponent(component.getName(), component.getText()), - component.getContentDescription() - //String.valueOf(component.getPositionX()), String.valueOf(component - // .getPositionY()), - // String.valueOf(component.getHeight()) - ); - - builder.append("<" + (elementName.isEmpty() ? "root" : elementName) + ">"); - - // sort - List children = component.getChildren(); - - children.sort(Comparator.comparingInt(DynGuiComponent::getComponentIndex)); - - for (DynGuiComponent child : children) { - visitComponents(child, builder); - } - - builder.append(""); - } - - private String getXmlElementName(String name) { - if (name == null) { - throw new RuntimeException("The XML element name is null"); - } - return name.replace("android.widget.", "").replace("android.view.", "").replace("android.webkit.", "") - .replace("android.support.", "").replace("$", "."); - } - - /** - * @return the states - */ - public HashMap getStates() { - return states; - } - - /** - * @param states the states to set - */ - public void setStates(HashMap states) { - this.states = states; - } - - /** - * @return the transitions - */ - public HashMap getTransitions() { - return transitions; - } - - /** - * @param transitions the transitions to set - */ - public void setTransitions(HashMap transitions) { - this.transitions = transitions; - } -} diff --git a/burt-tools/src/main/java/MainGraphGenerator.java b/burt-tools/src/main/java/MainGraphGenerator.java deleted file mode 100644 index 5b3fb58da..000000000 --- a/burt-tools/src/main/java/MainGraphGenerator.java +++ /dev/null @@ -1,210 +0,0 @@ -import edu.semeru.android.core.dao.AppDao; -import edu.semeru.android.core.entity.model.App; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.jgrapht.alg.KosarajuStrongConnectivityInspector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sealab.burt.qualitychecker.graph.AppGraph; -import sealab.burt.qualitychecker.graph.AppGraphInfo; -import sealab.burt.qualitychecker.graph.GraphState; -import sealab.burt.qualitychecker.graph.GraphTransition; -import seers.appcore.threads.ThreadExecutor; -import seers.appcore.threads.processor.ThreadParameters; -import seers.appcore.threads.processor.ThreadProcessor; -import seers.appcore.utils.JavaUtils; - -import javax.persistence.EntityManager; -import java.io.File; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -public class MainGraphGenerator { - - private static final Set> SYSTEMS_ALLOWED = JavaUtils.getSet( - new ImmutablePair<> ("com.evancharlton.mileage", "3.0.8") -// new ImmutablePair<> ("com.evancharlton.mileage", "3.1.1") -// new ImmutablePair<>("me.kuehle.carreport", "3.6.0"), -// new ImmutablePair<>("me.kuehle.carreport", "3.11.2") -// new ImmutablePair<>("com.markuspage.android.atimetracker", "0.20") -// new ImmutablePair<>("com.markuspage.android.atimetracker", "0.15") -// new ImmutablePair<>("nerd.tuxmobil.fahrplan.camp", "1.32.2"), -// new ImmutablePair<>("aarddict.android", "1.6.10") -// new ImmutablePair<>("aarddict.android", "1.6.10") -// new ImmutablePair<>("com.markuspage.android.atimetracker", "0.15") -// new ImmutablePair<>("org.gnucash.android", "2.1.3") -// new ImmutablePair<>("org.gnucash.android", "2.1.1") -// new ImmutablePair<>("org.gnucash.android", "2.2.0") -// new ImmutablePair<>("org.gnucash.android", "2.0.3") - ); - - private static final Logger LOGGER = LoggerFactory.getLogger(MainGraphGenerator.class); - - private static String outFolder = "C:\\Users\\ojcch\\Documents\\Projects\\Burt\\burt\\data\\graphs2"; - private static String screenShotsFolder = "C:/Users/ojcch/Documents/Projects/Amadeus/study-data/CS-Data/screenshots"; - private static String entityManager = DBUtils.DEFAULT_EM; - - // private static String outFolder = - // "C:/Users/ojcch/Documents/Projects/Andriod_bug_reproduction/testing-graphs2"; - // private static String screenShotsFolder = - // "C:/Users/ojcch/Documents/Projects/Andriod_bug_reproduction/backup/Data/screenshots"; - // private static String entityManager = MainGraphBasedAmadeus.dbEntityManager; - - public static void main(String[] args) throws Exception { - - EntityManager em = DBUtils.createEntityManager(entityManager); - - LOGGER.debug(entityManager); - - AppDao daoApp = new AppDao(); - - List apps = daoApp.findAll(em); - - List filteredApps = apps; - if (!SYSTEMS_ALLOWED.isEmpty()) { - filteredApps = apps.stream().filter(a -> SYSTEMS_ALLOWED.stream().anyMatch(pair -> pair.left.equals(a - .getPackageName()) && pair.right.equals(a.getVersion())) ) - .collect(Collectors.toList()); - } - - ThreadExecutor.executePaginated(filteredApps, AppThreadProcessor.class, new ThreadParameters(), 7); - - LOGGER.debug("Done"); - - } - - public static class AppThreadProcessor extends ThreadProcessor { - - private List apps; - - public AppThreadProcessor(ThreadParameters params) { - super(params); - apps = params.getListParam(App.class, ThreadExecutor.ELEMENTS_PARAM); - } - - @Override - public void executeJob() throws Exception { - - for (App app : apps) { - -// if (app.getName() == null || app.getName().isEmpty()) { -// continue; -// } - - String appNameVersion = app.getPackageName() + "-" + app.getVersion(); - LOGGER.debug("Processing system " + appNameVersion); - - try { - - GraphGenerator generator = new GraphGenerator(); - - AppGraphInfo graphInfo = generator.generateGraph(app); - AppGraph graph = graphInfo.getGraph(); - - if (graph.vertexSet().isEmpty()) { - LOGGER.warn("No graph for " + appNameVersion); - continue; - } - - String sysString = File.separator + app.getId() + "-" + graphInfo.getApp().getPackageName() + "-" - + graphInfo.getApp().getVersion(); - - File sysFolder = new File(outFolder + File.separator + sysString); - - if (sysFolder.exists()) { - FileUtils.deleteDirectory(sysFolder); - } - - String pathname = sysFolder + File.separator + sysString; - - // ------------------------------------------------------ - - File file = new File(pathname + "-graph.txt"); - String graphStr = graphInfo.graphToString(); - FileUtils.write(file, graphStr); - - // ------------------------------------------------------ - - KosarajuStrongConnectivityInspector inspector = new KosarajuStrongConnectivityInspector<>( - graph); - List> stronglyConnectedSets = inspector.stronglyConnectedSets(); - - String ccStr = getConnecterComponentsStr(stronglyConnectedSets); - File ccfile = new File(pathname + "-connected-comp.txt"); - FileUtils.write(ccfile, ccStr); - - // ------------------------------------------------------ - - String pathnameStates = sysFolder + File.separator + "states"; - String pathnameTransitions = sysFolder + File.separator + "transitions"; - - new File(pathnameStates).mkdir(); - new File(pathnameTransitions).mkdir(); - - Set edgeSet = graphInfo.getGraph().edgeSet(); - - for (GraphTransition edge : edgeSet) { - - String screenshotFile = edge.getStep().getScreenshotFile(); - - File srcFile = new File(screenShotsFolder + File.separator + screenshotFile); - - if (screenshotFile != null && screenshotFile.endsWith(".png") && srcFile.exists() - && srcFile.isFile()) { - - File destFile = new File(pathnameTransitions + File.separator + edge.getId() + ".png"); - FileUtils.copyFile(srcFile, destFile); - - GraphState sourceState = edge.getSourceState(); - - File destFile2 = new File( - pathnameStates + File.separator + sourceState.getUniqueHash() + ".png"); - if (!destFile2.exists()) { - FileUtils.copyFile(srcFile, destFile2); - } - - } - } - - // ------------------------------------------------------ - /*LOGGER.debug("Saving image"); - - mxGraph visualGraph = GraphUtils.getVisualGraph(graph, GraphLayout.CIRCLE); - BufferedImage image = mxCellRenderer.createBufferedImage(visualGraph, null, 1, Color.WHITE, true, - null); - ImageIO.write(image, "PNG", new File(pathname + ".png"));*/ - } catch (Exception e) { - LOGGER.error("Error for: " + appNameVersion, e); - } - } - } - - } - - private static String getConnecterComponentsStr(List> stronglyConnectedSets) { - - StringBuilder builder = new StringBuilder(); - - builder.append("# of components: " + stronglyConnectedSets.size()); - builder.append("\n"); - builder.append("\n"); - - for (int i = 0; i < stronglyConnectedSets.size(); i++) { - Set set = stronglyConnectedSets.get(i); - - builder.append("Component " + (i + 1)); - builder.append("\n"); - - set.forEach(s -> { - builder.append(s.getName() + ": " + s.getUnformattedXml()); - builder.append("\n"); - }); - - builder.append("\n"); - } - - return builder.toString(); - } - -} diff --git a/burt-quality-checker/src/main/java/sealab/burt/qualitychecker/graph/db/MainJSONGraphGenerator.java b/burt-tools/src/main/java/MainJSONGraphGenerator.java similarity index 97% rename from burt-quality-checker/src/main/java/sealab/burt/qualitychecker/graph/db/MainJSONGraphGenerator.java rename to burt-tools/src/main/java/MainJSONGraphGenerator.java index fb970bbbc..f05d6e486 100644 --- a/burt-quality-checker/src/main/java/sealab/burt/qualitychecker/graph/db/MainJSONGraphGenerator.java +++ b/burt-tools/src/main/java/MainJSONGraphGenerator.java @@ -1,5 +1,3 @@ -package sealab.burt.qualitychecker.graph.db; - import com.mxgraph.util.mxCellRenderer; import com.mxgraph.view.mxGraph; import lombok.extern.slf4j.Slf4j; @@ -17,7 +15,6 @@ import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; @@ -72,7 +69,7 @@ private static void generateAndSaveGraph(ImmutablePair system) t File graphFile = new File(pathname + "-graph.txt"); String graphStr = graphInfo.graphToString(); - FileUtils.write(graphFile, graphStr, Charset.defaultCharset()); + FileUtils.write(graphFile, graphStr, StandardCharsets.UTF_8); // ------------------------------------------------------ diff --git a/burt-tools/src/main/java/TestReadObject.java b/burt-tools/src/main/java/TestReadObject.java deleted file mode 100644 index 28f05361c..000000000 --- a/burt-tools/src/main/java/TestReadObject.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.io.File; -import java.io.FileInputStream; -import java.io.ObjectInputStream; - -public class TestReadObject { - - public static void main(String[] args) throws Exception { - try(ObjectInputStream i = new ObjectInputStream(new FileInputStream(new File("C:\\Users\\ojcch\\Documents" + - "\\Projects\\Burt\\burt\\data\\graphs2\\19-com.evancharlton.mileage-3.0.8\\19-com.evancharlton.mileage-3.0.8-graph.obj")))){ - Object obj = i.readObject(); - System.out.println(obj); - } - } -} diff --git a/burt-tools/src/main/java/Transform.java b/burt-tools/src/main/java/Transform.java deleted file mode 100644 index 868652755..000000000 --- a/burt-tools/src/main/java/Transform.java +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018, SEMERU - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those - * of the authors and should not be interpreted as representing official policies, - * either expressed or implied, of the FreeBSD Project. - *******************************************************************************/ - -import edu.semeru.android.core.entity.model.App; -import edu.semeru.android.core.entity.model.fusion.DynGuiComponent; -import sealab.burt.qualitychecker.graph.AppGuiComponent; -import sealab.burt.qualitychecker.graph.Appl; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * {Insert class description here} - * - * @author Carlos Bernal - */ -public class Transform { - /** - * @param pComponent - * @param pComponents - * @return - * @throws Exception - */ - public static AppGuiComponent getGuiComponent(DynGuiComponent pComponent, HashMap - pComponents) { - if (pComponent == null) { - return null; - } - - AppGuiComponent component = new AppGuiComponent(); - component.setDbId(pComponent.getId()); - component.setActivity(pComponent.getActivity()); - component.setCheckable(pComponent.isCheckable()); - component.setChecked(pComponent.isChecked()); - component.setClickable(pComponent.isClickable()); - component.setContentDescription(pComponent.getContentDescription()); - component.setEnabled(pComponent.isEnabled()); - component.setFocusable(pComponent.isFocusable()); - component.setFocused(pComponent.isFocused()); - component.setHeight(pComponent.getHeight()); - component.setIdXml(pComponent.getIdXml()); - component.setIndex(pComponent.getComponentIndex()); - component.setLongClickable(pComponent.isLongClickable()); - if (pComponents != null && pComponent.getParent() != null) { - AppGuiComponent parent = pComponents.get(pComponent.getParent().getId()); - // Transform the parent - parent = (parent == null) ? getGuiComponent(pComponent.getParent(), pComponents) : parent; - // Set relation - component.setParent(parent); - parent.getChildren().add(component); - } - component.setPassword(pComponent.isPassword()); - component.setRelativeLocation(pComponent.getRelativeLocation()); - component.setScrollable(pComponent.isScrollable()); - component.setSelected(pComponent.isSelected()); - component.setText(pComponent.getText()); - component.setTotalIndex(pComponent.getComponentTotalIndex()); - component.setType(pComponent.getName()); - component.setWidth(pComponent.getWidth()); - component.setX(pComponent.getPositionX()); - component.setY(pComponent.getPositionY()); - component.setCurrentWindow(pComponent.getCurrentWindow()); - if (pComponent.getScreen() != null) - component.setScreenId(pComponent.getScreen().getId()); - - // Add component to the map - if (pComponents != null) { - pComponents.put(pComponent.getId(), component); - } - return component; - } - - public static List getGuiComponents(List components) { - List result = new ArrayList<>(); - HashMap pComponents = new HashMap<>(); - for (DynGuiComponent dynGuiComponent : components) { - result.add(getGuiComponent(dynGuiComponent, pComponents)); - } - return result; - } - - public static Appl getAppl(App app) { - Appl appl = new Appl(); - appl.setId(app.getId()); - appl.setName(app.getName()); - appl.setApkPath(app.getApkPath()); - appl.setMainActivity(app.getMainActivity()); - appl.setVersion(app.getVersion()); - appl.setPackageName(app.getPackageName()); - return appl; - } -}