DASCA/com.logicalhacking.dasca.cr.../src/test/scala/com/logicalhacking/dasca/crosslanguage/test/AppTest.scala

146 lines
4.7 KiB
Scala

/*
* (C) Copyright 2016 The University of Sheffield.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*/
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
}