Skip to content

Commit

Permalink
jimple2cpg: Test Suite Consistency Cleanup (#2297)
Browse files Browse the repository at this point in the history
* Modified data-flow test suite to follow the Code2CpgFixture style
* Made use of `lazy` keyword for test CPG generation
* Added type annotations for public members in test suites
* Tests with multiple classes are broken up into multiple `should` groups
  • Loading branch information
DavidBakerEffendi authored Feb 22, 2023
1 parent e77f1ec commit 7910bd8
Show file tree
Hide file tree
Showing 39 changed files with 1,749 additions and 1,705 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package io.joern.jimple2cpg.querying

import io.joern.jimple2cpg.testfixtures.JimpleCode2CpgFixture
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.generated.Operators
import io.shiftleft.codepropertygraph.generated.nodes.Identifier
import io.shiftleft.semanticcpg.language.{ICallResolver, NoResolve, toNodeTypeStarters, _}
import io.shiftleft.semanticcpg.language.{toNodeTypeStarters, _}

class ArithmeticOperationsTests extends JimpleCode2CpgFixture {

val cpg = code("""
lazy val cpg: Cpg = code("""
| class Foo {
| static void main(int argc, char argv) {
| int a = 3;
Expand All @@ -20,9 +21,9 @@ class ArithmeticOperationsTests extends JimpleCode2CpgFixture {
| float h = 3.4f;
| }
| }
|""".stripMargin)
|""".stripMargin).cpg

val vars = Seq(
private val vars = Seq(
("a", "byte"),
("b", "double"),
("c", "double"),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.joern.jimple2cpg.querying

import io.joern.jimple2cpg.testfixtures.JimpleCode2CpgFixture
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.generated.Operators
import io.shiftleft.codepropertygraph.generated.nodes.{Call, Identifier, Literal}
import io.shiftleft.semanticcpg.language.{ICallResolver, NoResolve}
import io.shiftleft.semanticcpg.language._
import org.scalatest.Failed

class ArrayTests extends JimpleCode2CpgFixture {

val cpg = code("""
lazy val cpg: Cpg = code("""
|class Foo {
| public void foo() {
| int[] x = {0, 1, 2};
Expand All @@ -25,7 +25,7 @@ class ArrayTests extends JimpleCode2CpgFixture {
| x[1] = x[0] + 2;
| }
|}
|""".stripMargin)
|""".stripMargin).cpg

"should initialize array with three address code initialization expressions" in {
def m = cpg.method(".*foo.*")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.joern.jimple2cpg.querying

import io.joern.jimple2cpg.testfixtures.JimpleCode2CpgFixture
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.generated.nodes
import io.shiftleft.semanticcpg.language.NoResolve
import io.shiftleft.semanticcpg.language._
import io.shiftleft.semanticcpg.language.{NoResolve, _}

class CallTests extends JimpleCode2CpgFixture {

implicit val resolver: ICallResolver = NoResolve

val cpg = code("""
lazy val cpg: Cpg = code("""
| class Foo {
| static int add(int x, int y) {
| return x + y;
Expand All @@ -19,7 +19,7 @@ class CallTests extends JimpleCode2CpgFixture {
| return add(argc, 3);
| }
| }
|""".stripMargin)
|""".stripMargin).cpg

"should contain a call node for `add` with correct fields" in {
val List(x) = cpg.call("add").l
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package io.joern.jimple2cpg.querying

import io.joern.jimple2cpg.testfixtures.JimpleCode2CpgFixture
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.semanticcpg.language._

class CfgTests extends JimpleCode2CpgFixture {

val cpg = code("""
lazy val cpg: Cpg = code("""
|class Foo {
| int foo(int x, int y) {
| if (y < 10)
Expand All @@ -22,7 +23,7 @@ class CfgTests extends JimpleCode2CpgFixture {
| return;
| }
|}
""".stripMargin)
""".stripMargin).cpg

"should find that sink is control dependent on condition" in {
val controllers = cpg.call("sink").controlledBy.isCall.toSetMutable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.joern.jimple2cpg.querying

import io.joern.jimple2cpg.testfixtures.JimpleCode2CpgFixture
import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.codepropertygraph.generated.Operators
import io.shiftleft.codepropertygraph.generated.nodes._
import io.shiftleft.proto.cpg.Cpg.DispatchTypes
Expand All @@ -11,7 +12,7 @@ import io.shiftleft.semanticcpg.language._
*/
class ConstructorInvocationTests extends JimpleCode2CpgFixture {

val cpg = code("""
lazy val cpg: Cpg = code("""
|class Foo {
| int x;
|
Expand Down Expand Up @@ -49,7 +50,7 @@ class ConstructorInvocationTests extends JimpleCode2CpgFixture {
| bs[0] = new Bar(42);
| }
|}
|""".stripMargin)
|""".stripMargin).cpg

"it should create correct method nodes for constructors" in {
cpg.method.name(io.joern.x2cpg.Defines.ConstructorMethodName).where(_.fullName("^Foo.*")).l match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,104 +3,104 @@ package io.joern.jimple2cpg.querying
import io.joern.jimple2cpg.testfixtures.JimpleCode2CpgFixture
import io.shiftleft.semanticcpg.language.{NoResolve, _}

class DynamicCallGraphTests1 extends JimpleCode2CpgFixture {
class DynamicCallGraphTests extends JimpleCode2CpgFixture {

implicit val resolver: NoResolve.type = NoResolve

private val cpg = code("""
|class Foo {
|
| public static void main(String[] args){
| A b1 = new B();
| A c1 = new C();
|
| A b2 = b1;
| A c2 = c1;
|
| // what will get printed?
| b2.print(c2);
| }
|
| public static class A extends Object {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to A's print(A object)");
| }
| }
|
| public static class B extends A {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to B's print(A object)");
| }
| }
|
| public static class C extends B {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to C's print(A object)");
| }
| }
|
| public static class D extends A {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to D's print(A object)");
| }
| }
|
|}
|""".stripMargin)
"call from a nested super-class" should {
val cpg = code("""
|class Foo {
|
| public static void main(String[] args){
| A b1 = new B();
| A c1 = new C();
|
| A b2 = b1;
| A c2 = c1;
|
| // what will get printed?
| b2.print(c2);
| }
|
| public static class A extends Object {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to A's print(A object)");
| }
| }
|
| public static class B extends A {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to B's print(A object)");
| }
| }
|
| public static class C extends B {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to C's print(A object)");
| }
| }
|
| public static class D extends A {
| public void print(A object) {
| System.out.println("An instance of " + object.getClass().getSimpleName()
| + " was passed to D's print(A object)");
| }
| }
|
|}
|""".stripMargin).cpg

"should find that add is called by main" in {
cpg.method.name("print").caller.name.toSetMutable shouldBe Set("main")
}
"find that add is called by main" in {
cpg.method.name("print").caller.name.toSetMutable shouldBe Set("main")
}

"should account for print calls from all subclasses due to using CHA" in {
cpg.call.name("print").callee.definingTypeDecl.fullName.toSetMutable shouldBe Set(
"Foo$D",
"Foo$B",
"Foo$C",
"Foo$A"
)
"account for print calls from all subclasses due to using CHA" in {
cpg.call.name("print").callee.definingTypeDecl.fullName.toSetMutable shouldBe Set(
"Foo$D",
"Foo$B",
"Foo$C",
"Foo$A"
)
}
}

}

class DynamicCallGraphTests2 extends JimpleCode2CpgFixture {
"call from a method not overridden in a child class" should {
implicit val resolver: NoResolve.type = NoResolve
val cpg = code("""
|class Foo {
|
| private int x = 0;
|
| public int foo(int a) {
| this.x = a;
| return this.x;
| }
|}
|
|class Bar extends Foo {
|
| public int bar(int b) {
| return foo(b);
| }
|
|}
|""".stripMargin).cpg

implicit val resolver: NoResolve.type = NoResolve
"find that foo is still called with the derived full name" in {
cpg.call.name("foo").methodFullName.toSetMutable shouldBe Set("Bar.foo:int(int)")
}

private val cpg = code("""
|class Foo {
|
| private int x = 0;
|
| public int foo(int a) {
| this.x = a;
| return this.x;
| }
|}
|
|class Bar extends Foo {
|
| public int bar(int b) {
| return foo(b);
| }
|
|}
|""".stripMargin)
"find that foo is not defined and thus point to the superclass implementation" in {
cpg.method.name("foo").caller.name.toSetMutable shouldBe Set("bar")
}

"should find that foo is still called with the derived full name" in {
cpg.call.name("foo").methodFullName.toSetMutable shouldBe Set("Bar.foo:int(int)")
}

"should find that foo is not defined and thus point to the superclass implementation" in {
cpg.method.name("foo").caller.name.toSetMutable shouldBe Set("bar")
}
"account for call to inherited superclass" in {
cpg.call.name("foo").callee.definingTypeDecl.fullName.toSetMutable shouldBe Set("Foo")
}

"should account for call to inherited superclass" in {
cpg.call.name("foo").callee.definingTypeDecl.fullName.toSetMutable shouldBe Set("Foo")
}

}
Loading

0 comments on commit 7910bd8

Please sign in to comment.