/* * Copyright (c) 2016-2018 The University of Sheffield. * * All rights reserved. This program and the accompanying materials * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ package com.logicalhacking.dasca.crosslanguage.test import com.ibm.wala.classLoader.CallSiteReference import com.ibm.wala.ipa.callgraph.CGNode import com.logicalhacking.dasca.crosslanguage.util.Util import com.logicalhacking.dasca.crosslanguage.builder.CordovaCGBuilder import java.io.File import com.logicalhacking.dasca.crosslanguage.util.JavaScriptSourceLocation import com.logicalhacking.dasca.crosslanguage.util.JavaSourceLocation import com.logicalhacking.dasca.crosslanguage.util.SourceLocation import scala.collection.mutable.LinkedHashSet import com.logicalhacking.dasca.crosslanguage.builder.CrossBuilderOption import com.logicalhacking.dasca.crosslanguage.builder.MergedCallGraph import com.logicalhacking.dasca.crosslanguage.builder._ import com.ibm.wala.cast.ir.ssa.AstIRFactory import com.ibm.wala.cast.ir.ssa.AstIRFactory.AstIR import com.ibm.wala.classLoader.IMethod class AppTest { private var cg = null:MergedCallGraph; private var js2JavaHits = -1; private var js2JavaMisses = -1; private var js2JavaTotal = -1; private var java2JSHits = -1; private var java2JSMisses = -1; private var java2JSTotal = -1; def getJS2JavaHits() = { js2JavaHits } def getJS2JavaMisses() = { js2JavaMisses } def getJS2JavaErrors() = { js2JavaTotal - js2JavaHits } def getJS2JavaRecall() = { 100.0 * js2JavaHits / (js2JavaHits + js2JavaMisses) } def getJS2JavaPrecision() = { 100.0 * js2JavaHits / js2JavaTotal } def getJava2JSHits() = { java2JSHits } def getJava2JSMisses() = { java2JSMisses } def getJava2JSErrors() = { java2JSTotal - java2JSHits } def getJava2JSRecall() = { 100.0 * java2JSHits / (java2JSHits + java2JSMisses) } def getJava2JSPrecision() = { 100.0 * java2JSHits / java2JSTotal } private var truePositives = Set[(SourceLocation, SourceLocation)]() private var falseNegatives = Set[(SourceLocation, SourceLocation)]() private var falsePositives = Set[(SourceLocation, SourceLocation)]() def getTruePositives() = { truePositives } def getFalseNegatives() = { falseNegatives } def getFalsePositives() = { falsePositives } def getCallGraphSize() = cg.getNumberOfNodes def getJSCallGraphSize() = cg.jsCG.getNumberOfNodes def getJavaCallGraphSize() = cg.javaCG.getNumberOfNodes private var cgSize = -1 def analyze(apk:String, options:List[CrossBuilderOption], expectedConnections:Set[(SourceLocation, SourceLocation)]):Boolean = { val builder = CordovaCGBuilder(new File(getClass.getResource("/"+apk).getFile)); builder.setOptions(options:_*) cg = builder.createCallGraph val crossTargets = cg.getAllCrossTargets val convertedCrossTargets = convertToSourceLocationPairs(crossTargets) val (javaPairs, jsPairs) = convertedCrossTargets.partition({case (origin, target) => origin.isInstanceOf[JavaSourceLocation]}) java2JSTotal = javaPairs.size js2JavaTotal = jsPairs.size val (found, notFound) = expectedConnections.partition(p => convertedCrossTargets.contains(p)) java2JSHits = found.count(_._1.isInstanceOf[JavaSourceLocation]) js2JavaHits = found.count(_._1.isInstanceOf[JavaScriptSourceLocation]) java2JSMisses = notFound.count(_._1.isInstanceOf[JavaSourceLocation]) js2JavaMisses = notFound.count(_._1.isInstanceOf[JavaScriptSourceLocation]) truePositives = found falseNegatives = notFound falsePositives = convertedCrossTargets -- expectedConnections true } def convertToSourceLocationPairs(crossTargets: Map[(CGNode, CallSiteReference), LinkedHashSet[CGNode]]): Set[(SourceLocation, SourceLocation)] = { for ( origin <- crossTargets.keys; target <- crossTargets.get(origin).get ) yield { if (Util.isJavaNode(origin._1)) { target.getIR match { case ir: AstIR => (JavaSourceLocation(origin._1, origin._2), JavaScriptSourceLocation(ir)) case _ => (JavaSourceLocation(origin._1, origin._2), new JavaScriptSourceLocation(-1, -1, "unknown")) } } else { origin._1.getIR match { case ir: AstIR => (JavaScriptSourceLocation(ir, origin._2), JavaSourceLocation(target)) case _ => (new JavaScriptSourceLocation(-1, -1, "unknown"), JavaSourceLocation(target)) } } } }.toSet }