Skip to content

Commit 4bcf644

Browse files
committed
Added more type checking to tests
Signed-off-by: John Rofrano <johnnyroy@johnrofrano.com>
1 parent 7fa5447 commit 4bcf644

1 file changed

Lines changed: 105 additions & 43 deletions

File tree

tests/analysis/java/test_jcodeanalyzer.py

Lines changed: 105 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
import os
2222
import json
23-
from typing import Dict, List
23+
from typing import Dict, List, Tuple
2424
from unittest.mock import patch, MagicMock
2525
import networkx as nx
2626
from networkx import DiGraph
@@ -269,9 +269,11 @@ def test_get_symbol_table(test_fixture, analysis_json_fixture):
269269
target_files=None,
270270
)
271271
code_analyzer.application = None
272-
comp_unit = code_analyzer.get_symbol_table()
273-
assert comp_unit is not None
274-
assert isinstance(comp_unit, Dict)
272+
symbol_table = code_analyzer.get_symbol_table()
273+
assert symbol_table is not None
274+
assert isinstance(symbol_table, Dict)
275+
for _, comp_unit in symbol_table.items():
276+
assert isinstance(comp_unit, JCompilationUnit)
275277

276278

277279
def test_get_application_view(test_fixture, analysis_json_fixture):
@@ -298,7 +300,7 @@ def test_get_application_view(test_fixture, analysis_json_fixture):
298300
assert isinstance(app, JApplication)
299301

300302
# Test with source file
301-
code_analyzer.source_code = "dummy.java"
303+
code_analyzer.source_code = "./tests/resources/java/application/sample.daytrader8-1.2/src/main/java/com/ibm/websphere/samples/daytrader/web/websocket/ActionMessage.java"
302304
app = code_analyzer.get_application_view()
303305
assert app is not None
304306
assert isinstance(app, JApplication)
@@ -326,6 +328,7 @@ def test_get_system_dependency_graph(test_fixture, analysis_json_fixture):
326328
graph = code_analyzer.get_system_dependency_graph()
327329
assert graph is not None
328330
assert isinstance(graph, list)
331+
assert len(graph) > 0
329332
assert isinstance(graph[0], JGraphEdges)
330333

331334

@@ -342,7 +345,7 @@ def test_get_call_graph(test_fixture, analysis_json_fixture):
342345
source_code=None,
343346
analysis_backend_path=None,
344347
analysis_json_path=None,
345-
analysis_level=AnalysisLevel.symbol_table,
348+
analysis_level=AnalysisLevel.call_graph,
346349
use_graalvm_binary=False,
347350
eager_analysis=False,
348351
target_files=None,
@@ -352,7 +355,7 @@ def test_get_call_graph(test_fixture, analysis_json_fixture):
352355
assert isinstance(graph, DiGraph)
353356

354357
# test for symbol table
355-
code_analyzer.analysis_level = "symbol_table"
358+
code_analyzer.analysis_level = AnalysisLevel.symbol_table
356359
graph = code_analyzer.get_call_graph()
357360
assert graph is not None
358361
assert isinstance(graph, DiGraph)
@@ -407,20 +410,20 @@ def test_get_all_callers(test_fixture, analysis_json_fixture):
407410
all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", False)
408411
assert all_callers is not None
409412
assert isinstance(all_callers, Dict)
413+
assert len(all_callers) > 0
410414
assert "caller_details" in all_callers
411415
assert len(all_callers["caller_details"]) == 18
412416
for method in all_callers["caller_details"]:
413417
assert isinstance(method["caller_method"], JMethodDetail)
414418

419+
# Call using symbol table
420+
415421
# TODO: This currently doesn't work. Code has bad call as seen in this error message:
416422
# TypeError: JavaSitter.get_calling_lines() missing 1 required positional argument: 'is_target_method_a_constructor'
417-
# Uncomment when code is fixed.
418-
419-
# # Call using symbol table
420-
# all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", True)
421-
# assert all_callers is not None
422-
# assert isinstance(all_callers, Dict)
423-
# assert "caller_details" in all_callers
423+
all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", True)
424+
assert all_callers is not None
425+
assert isinstance(all_callers, Dict)
426+
assert "caller_details" in all_callers
424427

425428

426429
def test_get_all_callees(test_fixture, analysis_json_fixture):
@@ -443,20 +446,21 @@ def test_get_all_callees(test_fixture, analysis_json_fixture):
443446
)
444447

445448
# Call without using symbol table
446-
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", False)
449+
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "printCollection(String, Collection)", False)
447450
assert all_callees is not None
448451
assert isinstance(all_callees, Dict)
449452
assert "callee_details" in all_callees
450-
assert len(all_callees["callee_details"]) == 0
453+
assert len(all_callees["callee_details"]) == 2
451454

452-
# Call using symbol table
453-
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", True)
455+
# Call using the symbol table
456+
457+
# TODO: Throws the following exception
458+
# TypeError: JavaSitter.get_calling_lines() missing 1 required positional argument: 'is_target_method_a_constructor'
459+
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "printCollection(String, Collection)", True)
454460
assert all_callees is not None
455461
assert isinstance(all_callees, Dict)
456-
# TODO: Bug, the Dict is empty.
457-
# need to uncomment when code is fixed
458-
# assert "callee_details" in all_callees
459-
# assert len(all_callees["callee_details"]) == 0
462+
assert "callee_details" in all_callees
463+
assert len(all_callees["callee_details"]) == 2
460464

461465

462466
def test_get_all_methods_in_application(test_fixture, analysis_json_fixture):
@@ -480,6 +484,14 @@ def test_get_all_methods_in_application(test_fixture, analysis_json_fixture):
480484
all_methods = code_analyzer.get_all_methods_in_application()
481485
assert all_methods is not None
482486
assert isinstance(all_methods, Dict)
487+
assert len(all_methods) > 0
488+
# Validate structure
489+
for _, method in all_methods.items():
490+
assert method is not None
491+
assert isinstance(method, Dict)
492+
for _, callable in method.items():
493+
assert callable is not None
494+
assert isinstance(callable, JCallable)
483495

484496

485497
def test_get_all_classes(test_fixture, analysis_json_fixture):
@@ -501,9 +513,14 @@ def test_get_all_classes(test_fixture, analysis_json_fixture):
501513
target_files=None,
502514
)
503515

504-
all_methods = code_analyzer.get_all_classes()
505-
assert all_methods is not None
506-
assert isinstance(all_methods, Dict)
516+
all_classes = code_analyzer.get_all_classes()
517+
assert all_classes is not None
518+
assert isinstance(all_classes, Dict)
519+
assert len(all_classes) > 0
520+
# Validate structure
521+
for _, a_class in all_classes.items():
522+
assert a_class is not None
523+
assert isinstance(a_class, JType)
507524

508525

509526
def test_get_class(test_fixture, analysis_json_fixture):
@@ -608,6 +625,10 @@ def test_get_all_methods_in_class(test_fixture, analysis_json_fixture):
608625
assert all_methods is not None
609626
assert isinstance(all_methods, Dict)
610627
assert len(all_methods) > 0
628+
# Validate structure
629+
for _, method in all_methods.items():
630+
assert method is not None
631+
assert isinstance(method, JCallable)
611632

612633

613634
def test_get_all_constructors(test_fixture, analysis_json_fixture):
@@ -629,10 +650,21 @@ def test_get_all_constructors(test_fixture, analysis_json_fixture):
629650
target_files=None,
630651
)
631652

653+
# Test if it finds the 3 constructors in AccountDataBean
632654
all_constructors = code_analyzer.get_all_constructors("com.ibm.websphere.samples.daytrader.entities.AccountDataBean")
633655
assert all_constructors is not None
634656
assert isinstance(all_constructors, Dict)
635657
assert len(all_constructors) == 3
658+
# Validate structure
659+
for _, constructor in all_constructors.items():
660+
assert constructor is not None
661+
assert isinstance(constructor, JCallable)
662+
663+
# Test class with no constructors
664+
all_constructors = code_analyzer.get_all_constructors("com.ibm.websphere.samples.daytrader.util.FinancialUtils")
665+
assert all_constructors is not None
666+
assert isinstance(all_constructors, Dict)
667+
assert len(all_constructors) == 0
636668

637669

638670
def test_get_all_sub_classes(test_fixture, analysis_json_fixture):
@@ -648,15 +680,17 @@ def test_get_all_sub_classes(test_fixture, analysis_json_fixture):
648680
source_code=None,
649681
analysis_backend_path=None,
650682
analysis_json_path=None,
651-
analysis_level=AnalysisLevel.call_graph,
683+
analysis_level=AnalysisLevel.symbol_table,
652684
use_graalvm_binary=False,
653685
eager_analysis=False,
654686
target_files=None,
655687
)
656688

657-
all_subclasses = code_analyzer.get_all_sub_classes("com.ibm.websphere.samples.daytrader.TradeAction")
689+
all_subclasses = code_analyzer.get_all_sub_classes("javax.ws.rs.core.Application")
658690
assert all_subclasses is not None
659691
assert isinstance(all_subclasses, Dict)
692+
assert len(all_subclasses) == 1
693+
assert "com.ibm.websphere.samples.daytrader.jaxrs.JAXRSApplication" in all_subclasses
660694

661695

662696
def test_get_all_fields(test_fixture, analysis_json_fixture):
@@ -709,9 +743,13 @@ def test_get_all_nested_classes(test_fixture, analysis_json_fixture):
709743
target_files=None,
710744
)
711745

712-
all_nested_classes = code_analyzer.get_all_nested_classes("com.ibm.websphere.samples.daytrader.TradeAction")
746+
# TODO: This should return 1 but return 0
747+
748+
# Test with a KeyBlock that has nested KeyBlockIterator
749+
all_nested_classes = code_analyzer.get_all_nested_classes("com.ibm.websphere.samples.daytrader.util.KeyBlock")
713750
assert all_nested_classes is not None
714751
assert isinstance(all_nested_classes, List)
752+
assert len(all_nested_classes) == 1
715753

716754
# Handle class not found
717755
all_nested_classes = code_analyzer.get_all_nested_classes("com.not.Found")
@@ -739,12 +777,14 @@ def test_get_extended_classes(test_fixture, analysis_json_fixture):
739777
target_files=None,
740778
)
741779

742-
all_extended_classes = code_analyzer.get_extended_classes("com.ibm.websphere.samples.daytrader.TradeAction")
780+
all_extended_classes = code_analyzer.get_extended_classes("com.ibm.websphere.samples.daytrader.util.TradeRunTimeModeLiteral")
743781
assert all_extended_classes is not None
744782
assert isinstance(all_extended_classes, List)
783+
assert len(all_extended_classes) == 1
784+
assert "javax.enterprise.util.AnnotationLiteral<com.ibm.websphere.samples.daytrader.interfaces.RuntimeMode>" in all_extended_classes
745785

746-
# Handle class not found
747-
all_extended_classes = code_analyzer.get_extended_classes("com.not.Found")
786+
# Test with class that is not extended
787+
all_extended_classes = code_analyzer.get_extended_classes("com.ibm.websphere.samples.daytrader.entities.HoldingDataBean")
748788
assert all_extended_classes is not None
749789
assert isinstance(all_extended_classes, List)
750790
assert len(all_extended_classes) == 0
@@ -769,13 +809,16 @@ def test_get_implemented_interfaces(test_fixture, analysis_json_fixture):
769809
target_files=None,
770810
)
771811

772-
# Call without using symbol table
773-
all_interfaces = code_analyzer.get_implemented_interfaces("com.ibm.websphere.samples.daytrader.TradeAction")
812+
# Call class that implements 2 interfaces
813+
all_interfaces = code_analyzer.get_implemented_interfaces("com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect")
774814
assert all_interfaces is not None
775815
assert isinstance(all_interfaces, List)
816+
assert len(all_interfaces) == 2
817+
assert "com.ibm.websphere.samples.daytrader.interfaces.TradeServices" in all_interfaces
818+
assert "java.io.Serializable" in all_interfaces
776819

777-
# Handle class not found
778-
all_interfaces = code_analyzer.get_implemented_interfaces("com.not.Found")
820+
# Call class that implements no interfaces
821+
all_interfaces = code_analyzer.get_implemented_interfaces("com.ibm.websphere.samples.daytrader.util.TradeConfig")
779822
assert all_interfaces is not None
780823
assert isinstance(all_interfaces, List)
781824
assert len(all_interfaces) == 0
@@ -800,16 +843,19 @@ def test_get_class_call_graph_using_symbol_table(test_fixture, analysis_json_fix
800843
target_files=None,
801844
)
802845

803-
# TODO: The code seems to be broken for this case
804-
# # Call with method signature
805-
# all_call_graph = code_analyzer.get_class_call_graph_using_symbol_table("com.ibm.websphere.samples.daytrader.TradeAction", "getQuote(String)")
806-
# assert all_call_graph is not None
807-
# assert isinstance(all_call_graph, List)
846+
# TODO: I could be wrong but I think these should not be zero?
847+
848+
# Call with method signature
849+
all_call_graph = code_analyzer.get_class_call_graph_using_symbol_table("com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", "getStatement(Connection, String)")
850+
assert all_call_graph is not None
851+
assert isinstance(all_call_graph, List)
852+
assert len(all_call_graph) == 0
808853

809854
# Call without method signature
810-
all_call_graph = code_analyzer.get_class_call_graph_using_symbol_table("com.ibm.websphere.samples.daytrader.TradeAction", None)
855+
all_call_graph = code_analyzer.get_class_call_graph_using_symbol_table("com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", None)
811856
assert all_call_graph is not None
812857
assert isinstance(all_call_graph, List)
858+
assert len(all_call_graph) == 0
813859

814860

815861
def test_get_class_call_graph(test_fixture, analysis_json_fixture):
@@ -832,14 +878,22 @@ def test_get_class_call_graph(test_fixture, analysis_json_fixture):
832878
)
833879

834880
# Call with method signature
835-
class_call_graph = code_analyzer.get_class_call_graph("com.ibm.websphere.samples.daytrader.TradeAction", "getQuote(String)")
881+
class_call_graph = code_analyzer.get_class_call_graph(
882+
"com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", "createHolding(Connection, int, String, double, BigDecimal)"
883+
)
836884
assert class_call_graph is not None
837885
assert isinstance(class_call_graph, List)
886+
assert len(class_call_graph) == 4
887+
for method in class_call_graph:
888+
assert isinstance(method, Tuple)
889+
assert isinstance(method[0], JMethodDetail)
890+
assert isinstance(method[1], JMethodDetail)
838891

839892
# Call without method signature
840-
class_call_graph = code_analyzer.get_class_call_graph("com.ibm.websphere.samples.daytrader.TradeAction", None)
893+
class_call_graph = code_analyzer.get_class_call_graph("com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", None)
841894
assert class_call_graph is not None
842895
assert isinstance(class_call_graph, List)
896+
assert len(class_call_graph) > 0
843897

844898

845899
def test_get_all_entry_point_methods(test_fixture, analysis_json_fixture):
@@ -866,6 +920,11 @@ def test_get_all_entry_point_methods(test_fixture, analysis_json_fixture):
866920
assert entry_point_methods is not None
867921
assert isinstance(entry_point_methods, Dict)
868922
assert len(entry_point_methods) > 0
923+
# Validate structure
924+
for _, entry_point in entry_point_methods.items():
925+
assert isinstance(entry_point, Dict)
926+
for _, method in entry_point.items():
927+
assert isinstance(method, JCallable)
869928

870929

871930
def test_get_all_entry_point_classes(test_fixture, analysis_json_fixture):
@@ -892,3 +951,6 @@ def test_get_all_entry_point_classes(test_fixture, analysis_json_fixture):
892951
assert entry_point_classes is not None
893952
assert isinstance(entry_point_classes, Dict)
894953
assert len(entry_point_classes) > 0
954+
# Validate structure
955+
for _, entry_point in entry_point_classes.items():
956+
assert isinstance(entry_point, JType)

0 commit comments

Comments
 (0)