-
Notifications
You must be signed in to change notification settings - Fork 278
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[rubysrc2cpg] Add AST tests for basic operations (#3076)
Added assign, attribute, binop, and boolop tests.
- Loading branch information
Showing
4 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
176 changes: 176 additions & 0 deletions
176
...frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/passes/ast/AssignCpgTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package io.joern.rubysrc2cpg.passes.ast | ||
|
||
import io.joern.rubysrc2cpg.testfixtures.RubyCode2CpgFixture | ||
import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, NodeTypes, DispatchTypes, Operators, nodes} | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal | ||
|
||
class AssignCpgTests extends RubyCode2CpgFixture { | ||
"single target assign" should { | ||
val cpg = code("""x = 2""".stripMargin) | ||
|
||
// TODO: .code property need to be fixed | ||
"test assignment node properties" ignore { | ||
val assignCall = cpg.call.methodFullName(Operators.assignment).head | ||
assignCall.code shouldBe "x = 2" // "=" | ||
assignCall.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH | ||
assignCall.lineNumber shouldBe Some(1) | ||
assignCall.columnNumber shouldBe Some(1) | ||
} | ||
|
||
"test assignment node ast children" in { | ||
cpg.call | ||
.methodFullName(Operators.assignment) | ||
.astChildren | ||
.order(1) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "x" | ||
cpg.call | ||
.methodFullName(Operators.assignment) | ||
.astChildren | ||
.order(2) | ||
.isLiteral | ||
.head | ||
.code shouldBe "2" | ||
} | ||
|
||
"test assignment node arguments" in { | ||
cpg.call | ||
.methodFullName(Operators.assignment) | ||
.argument | ||
.argumentIndex(1) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "x" | ||
cpg.call | ||
.methodFullName(Operators.assignment) | ||
.argument | ||
.argumentIndex(2) | ||
.isLiteral | ||
.head | ||
.code shouldBe "2" | ||
} | ||
} | ||
|
||
"nested decomposing assign" should { | ||
val cpg = code("""x, (y, z) = [1, [2, 3]]""".stripMargin) | ||
|
||
def getSurroundingBlock: nodes.Block = { | ||
cpg.all.collect { case block: nodes.Block if block.code != "" => block }.head | ||
} | ||
|
||
"test block exists" in { | ||
// Throws if block does not exist. | ||
getSurroundingBlock | ||
} | ||
|
||
// TODO: .code property need to be fixed | ||
"test block node properties" ignore { | ||
val block = getSurroundingBlock | ||
block.code shouldBe | ||
"""tmp0 = list | ||
|x = tmp0[0] | ||
|y = tmp0[1][0] | ||
|z = tmp0[1][1]""".stripMargin | ||
block.lineNumber shouldBe Some(1) | ||
} | ||
|
||
// TODO: Need to fix the local variables | ||
"test local node" ignore { | ||
cpg.method.name("Test0.rb::program").local.name("tmp0").headOption should not be empty | ||
} | ||
|
||
"test tmp variable assignment" in { | ||
val block = getSurroundingBlock | ||
val tmpAssignNode = block.astChildren.isCall.sortBy(_.order).head | ||
// tmpAssignNode.code shouldBe "tmp0 = list" | ||
tmpAssignNode.methodFullName shouldBe Operators.assignment | ||
tmpAssignNode.lineNumber shouldBe Some(1) | ||
} | ||
|
||
// TODO: Fix the code property of the Block node & the order too | ||
"test assignments to targets" ignore { | ||
val block = getSurroundingBlock | ||
val assignNodes = block.astChildren.isCall.sortBy(_.order).tail | ||
assignNodes.map(_.code) should contain theSameElementsInOrderAs List( | ||
"x = tmp0[0]", | ||
"y = tmp0[1][0]", | ||
"z = tmp0[1][1]" | ||
) | ||
assignNodes.map(_.lineNumber.get) should contain theSameElementsInOrderAs List(1, 1, 1) | ||
} | ||
|
||
} | ||
|
||
"array destructuring assign" should { | ||
val cpg = code("""x, *, y = [1, 2, 3, 5]""".stripMargin) | ||
|
||
def getSurroundingBlock: nodes.Block = { | ||
cpg.all.collect { case block: nodes.Block if block.code != "" => block }.head | ||
} | ||
|
||
"test block exists" in { | ||
// Throws if block does not exist. | ||
getSurroundingBlock | ||
} | ||
|
||
// TODO: .code property need to be fixed | ||
"test block node properties" ignore { | ||
val block = getSurroundingBlock | ||
block.code shouldBe | ||
"""tmp0 = list | ||
|x = tmp0[0] | ||
|y = tmp0[1][0] | ||
|z = tmp0[1][1]""".stripMargin | ||
block.astChildren.length shouldBe 4 | ||
cpg.identifier("x").isEmpty shouldBe false | ||
cpg.identifier("y").isEmpty shouldBe false | ||
cpg.identifier("z").isEmpty shouldBe false | ||
|
||
} | ||
|
||
// TODO: Need to fix the local variables | ||
"test local node" ignore { | ||
cpg.method.name("Test0.rb::program").local.name("tmp0").headOption should not be empty | ||
} | ||
|
||
} | ||
|
||
"multi target assign" should { | ||
val cpg = code("""x = y = "abcd" """.stripMargin) | ||
|
||
def getSurroundingBlock: nodes.Block = { | ||
cpg.all.collect { case block: nodes.Block if block.code != "" => block }.head | ||
} | ||
|
||
"test block exists" in { | ||
// Throws if block does not exist. | ||
getSurroundingBlock | ||
} | ||
|
||
// TODO: Fix the code property of the Block node | ||
"test block node properties" ignore { | ||
val block = getSurroundingBlock | ||
block.code shouldBe | ||
"""tmp0 = list | ||
|x = tmp0 | ||
|y = tmp0""".stripMargin | ||
block.lineNumber shouldBe Some(1) | ||
} | ||
|
||
// TODO: Need to fix the local variables | ||
"test local node" ignore { | ||
cpg.method.name("Test0.rb::program").local.name("tmp0").headOption should not be empty | ||
} | ||
|
||
// TODO: Need to fix the code property | ||
"test tmp variable assignment" ignore { | ||
val block = getSurroundingBlock | ||
val tmpAssignNode = block.astChildren.isCall.sortBy(_.order).head | ||
tmpAssignNode.code shouldBe "tmp0 = list" | ||
tmpAssignNode.methodFullName shouldBe Operators.assignment | ||
tmpAssignNode.lineNumber shouldBe Some(1) | ||
} | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
...ntends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/passes/ast/AttributeCpgTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package io.joern.rubysrc2cpg.passes.ast | ||
|
||
import io.joern.rubysrc2cpg.testfixtures.RubyCode2CpgFixture | ||
import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, NodeTypes, DispatchTypes, Operators, nodes} | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal | ||
|
||
class AttributeCpgTests extends RubyCode2CpgFixture { | ||
val cpg = code("""x.y""".stripMargin) | ||
|
||
// TODO: Class Modeling testcase | ||
"test field access call node properties" ignore { | ||
val callNode = cpg.call.methodFullName(Operators.fieldAccess).head | ||
callNode.code shouldBe "x.y" | ||
callNode.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH | ||
callNode.lineNumber shouldBe Some(1) | ||
} | ||
|
||
// TODO: Class Modeling testcase | ||
"test field access call ast children" ignore { | ||
cpg.call | ||
.methodFullName(Operators.fieldAccess) | ||
.astChildren | ||
.order(1) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "x" | ||
cpg.call | ||
.methodFullName(Operators.fieldAccess) | ||
.astChildren | ||
.order(2) | ||
.isFieldIdentifier | ||
.head | ||
.code shouldBe "y" | ||
} | ||
|
||
// TODO: Class Modeling testcase | ||
"test field access call arguments" ignore { | ||
cpg.call | ||
.methodFullName(Operators.fieldAccess) | ||
.argument | ||
.argumentIndex(1) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "x" | ||
cpg.call | ||
.methodFullName(Operators.fieldAccess) | ||
.argument | ||
.argumentIndex(2) | ||
.isFieldIdentifier | ||
.head | ||
.code shouldBe "y" | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
.../frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/passes/ast/BinOpCpgTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package io.joern.rubysrc2cpg.passes.ast | ||
|
||
import io.joern.rubysrc2cpg.testfixtures.RubyCode2CpgFixture | ||
import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, NodeTypes, DispatchTypes, Operators, nodes} | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal | ||
|
||
class BinOpCpgTests extends RubyCode2CpgFixture { | ||
val cpg = code("""1 + 2""".stripMargin) | ||
|
||
"test binOp 'add' call node properties" in { | ||
val additionCall = cpg.call.methodFullName(Operators.addition).head | ||
additionCall.code shouldBe "1 + 2" | ||
additionCall.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH | ||
additionCall.lineNumber shouldBe Some(1) | ||
// TODO additionCall.columnNumber shouldBe Some(1) | ||
} | ||
|
||
"test binOp 'add' ast children" in { | ||
cpg.call | ||
.methodFullName(Operators.addition) | ||
.astChildren | ||
.order(1) | ||
.isLiteral | ||
.head | ||
.code shouldBe "1" | ||
cpg.call | ||
.methodFullName(Operators.addition) | ||
.astChildren | ||
.order(2) | ||
.isLiteral | ||
.head | ||
.code shouldBe "2" | ||
} | ||
|
||
"test binOp 'add' arguments" in { | ||
cpg.call | ||
.methodFullName(Operators.addition) | ||
.argument | ||
.argumentIndex(1) | ||
.isLiteral | ||
.head | ||
.code shouldBe "1" | ||
cpg.call | ||
.methodFullName(Operators.addition) | ||
.argument | ||
.argumentIndex(2) | ||
.isLiteral | ||
.head | ||
.code shouldBe "2" | ||
} | ||
|
||
} |
69 changes: 69 additions & 0 deletions
69
...frontends/rubysrc2cpg/src/test/scala/io/joern/rubysrc2cpg/passes/ast/BoolOpCpgTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package io.joern.rubysrc2cpg.passes.ast | ||
|
||
import io.joern.rubysrc2cpg.testfixtures.RubyCode2CpgFixture | ||
import io.shiftleft.codepropertygraph.generated.{EvaluationStrategies, NodeTypes, DispatchTypes, Operators, nodes} | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal | ||
|
||
class BoolOpCpgTests extends RubyCode2CpgFixture { | ||
val cpg = code("""x or y or z""".stripMargin) | ||
|
||
"test boolOp 'or' call node properties" in { | ||
val orCall = cpg.call.head | ||
// val orCall = cpg.call.methodFullName(Operators.logicalOr).head | ||
orCall.code shouldBe "x or y or z" | ||
orCall.dispatchType shouldBe DispatchTypes.STATIC_DISPATCH | ||
orCall.lineNumber shouldBe Some(1) | ||
// TODO orCall.columnNumber shouldBe Some(3) | ||
} | ||
|
||
// TODO: Fix this multi logicalOr operation | ||
"test boolOp 'or' ast children" ignore { | ||
cpg.call | ||
.methodFullName(Operators.logicalOr) | ||
.astChildren | ||
.order(1) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "x" | ||
cpg.call | ||
.methodFullName(Operators.logicalOr) | ||
.astChildren | ||
.order(2) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "y" | ||
cpg.call | ||
.methodFullName(Operators.logicalOr) | ||
.astChildren | ||
.order(3) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "z" | ||
} | ||
|
||
// TODO: Fix this multi logicalOr operation arguments | ||
"test boolOp 'or' arguments" ignore { | ||
cpg.call | ||
.methodFullName(Operators.logicalOr) | ||
.argument | ||
.argumentIndex(1) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "x" | ||
cpg.call | ||
.methodFullName(Operators.logicalOr) | ||
.argument | ||
.argumentIndex(2) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "y" | ||
cpg.call | ||
.methodFullName(Operators.logicalOr) | ||
.argument | ||
.argumentIndex(3) | ||
.isIdentifier | ||
.head | ||
.code shouldBe "z" | ||
} | ||
} |