"""Tests for Java analyzer."""
import pytest
from scantool.analyzers.java_analyzer import JavaAnalyzer
from scantool.analyzers.models import ImportInfo, EntryPointInfo
@pytest.fixture
def analyzer():
"""Create Java analyzer instance."""
return JavaAnalyzer()
def test_extensions(analyzer):
"""Test that Java analyzer supports correct extensions."""
extensions = analyzer.get_extensions()
assert ".java" in extensions
assert len(extensions) == 1
def test_language_name(analyzer):
"""Test language name."""
assert analyzer.get_language_name() == "Java"
def test_extract_imports_simple(analyzer):
"""Test extraction of simple import statements."""
content = """
package com.example.app;
import java.util.List;
import java.util.ArrayList;
import java.io.File;
"""
imports = analyzer.extract_imports("Example.java", content)
assert len(imports) == 3
assert any(imp.target_module == "java.util.List" for imp in imports)
assert any(imp.target_module == "java.util.ArrayList" for imp in imports)
assert any(imp.target_module == "java.io.File" for imp in imports)
assert all(imp.import_type == "import" for imp in imports)
def test_extract_imports_wildcard(analyzer):
"""Test extraction of wildcard imports."""
content = """
import java.util.*;
import java.io.*;
import org.springframework.web.*;
"""
imports = analyzer.extract_imports("Example.java", content)
assert len(imports) == 3
assert any(
imp.target_module == "java.util.*" and imp.import_type == "wildcard"
for imp in imports
)
assert any(
imp.target_module == "java.io.*" and imp.import_type == "wildcard"
for imp in imports
)
assert any(
imp.target_module == "org.springframework.web.*"
and imp.import_type == "wildcard"
for imp in imports
)
def test_extract_imports_static(analyzer):
"""Test extraction of static imports."""
content = """
import static org.junit.Assert.*;
import static java.lang.Math.PI;
import static com.example.Utils.helper;
"""
imports = analyzer.extract_imports("Example.java", content)
assert len(imports) == 3
# Check static imports
junit_import = next(imp for imp in imports if "Assert" in imp.target_module)
assert junit_import.import_type == "static"
assert junit_import.target_module == "org.junit.Assert.*"
assert "Assert.*" in junit_import.imported_names
pi_import = next(imp for imp in imports if "PI" in imp.target_module)
assert pi_import.import_type == "static"
assert pi_import.target_module == "java.lang.Math.PI"
assert "Math.PI" in pi_import.imported_names
helper_import = next(imp for imp in imports if "helper" in imp.target_module)
assert helper_import.import_type == "static"
assert helper_import.target_module == "com.example.Utils.helper"
def test_extract_imports_mixed(analyzer):
"""Test extraction of mixed regular and static imports."""
content = """
package com.example;
import java.util.List;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
import static java.util.Collections.*;
import org.springframework.boot.SpringApplication;
"""
imports = analyzer.extract_imports("Example.java", content)
assert len(imports) == 5
# Count by type
regular_imports = [imp for imp in imports if imp.import_type == "import"]
static_imports = [imp for imp in imports if imp.import_type == "static"]
assert len(regular_imports) == 3
assert len(static_imports) == 2
def test_find_entry_points_main_method_standard(analyzer):
"""Test detection of standard main method."""
content = """
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
"""
entry_points = analyzer.find_entry_points("Main.java", content)
main_entries = [ep for ep in entry_points if ep.type == "main_method"]
assert len(main_entries) == 1
assert main_entries[0].name == "Main.main"
def test_find_entry_points_main_method_array_after(analyzer):
"""Test detection of main method with array brackets after parameter."""
content = """
public class Main {
public static void main(String args[]) {
System.out.println("Hello!");
}
}
"""
entry_points = analyzer.find_entry_points("Main.java", content)
main_entries = [ep for ep in entry_points if ep.type == "main_method"]
assert len(main_entries) == 1
assert main_entries[0].name == "Main.main"
def test_find_entry_points_main_method_varargs(analyzer):
"""Test detection of main method with varargs."""
content = """
public class Main {
public static void main(String... args) {
System.out.println("Varargs!");
}
}
"""
entry_points = analyzer.find_entry_points("Main.java", content)
main_entries = [ep for ep in entry_points if ep.type == "main_method"]
assert len(main_entries) == 1
def test_find_entry_points_spring_boot_application(analyzer):
"""Test detection of @SpringBootApplication annotation."""
content = """
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
"""
entry_points = analyzer.find_entry_points("DemoApplication.java", content)
# Should find both @SpringBootApplication and main method
assert len(entry_points) >= 2
spring_entries = [ep for ep in entry_points if ep.type == "spring_boot_app"]
assert len(spring_entries) == 1
assert spring_entries[0].name == "DemoApplication"
assert spring_entries[0].framework == "Spring Boot"
main_entries = [ep for ep in entry_points if ep.type == "main_method"]
assert len(main_entries) == 1
def test_find_entry_points_web_servlet(analyzer):
"""Test detection of @WebServlet annotation."""
content = """
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
response.getWriter().println("Hello!");
}
}
"""
entry_points = analyzer.find_entry_points("HelloServlet.java", content)
servlet_entries = [ep for ep in entry_points if ep.type == "servlet"]
assert len(servlet_entries) == 1
assert servlet_entries[0].name == "HelloServlet:/hello"
assert servlet_entries[0].framework == "Servlet"
def test_find_entry_points_web_servlet_complex(analyzer):
"""Test detection of @WebServlet with complex annotation."""
content = """
@WebServlet(name = "UserServlet", urlPatterns = {"/users", "/user"})
public class UserServlet extends HttpServlet {
}
"""
entry_points = analyzer.find_entry_points("UserServlet.java", content)
servlet_entries = [ep for ep in entry_points if ep.type == "servlet"]
assert len(servlet_entries) == 1
assert "UserServlet" in servlet_entries[0].name
def test_find_entry_points_rest_controller(analyzer):
"""Test detection of @RestController annotation."""
content = """
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
}
"""
entry_points = analyzer.find_entry_points("UserController.java", content)
rest_entries = [ep for ep in entry_points if ep.type == "rest_controller"]
assert len(rest_entries) == 1
assert rest_entries[0].name == "UserController"
assert rest_entries[0].framework == "Spring"
def test_find_entry_points_controller(analyzer):
"""Test detection of @Controller annotation."""
content = """
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "index";
}
}
"""
entry_points = analyzer.find_entry_points("HomeController.java", content)
controller_entries = [ep for ep in entry_points if ep.type == "controller"]
assert len(controller_entries) == 1
assert controller_entries[0].name == "HomeController"
assert controller_entries[0].framework == "Spring"
def test_find_entry_points_multiple(analyzer):
"""Test detection of multiple entry points in one file."""
content = """
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
"""
entry_points = analyzer.find_entry_points("Application.java", content)
# Should find both annotations and main method
assert len(entry_points) == 2
types = {ep.type for ep in entry_points}
assert "spring_boot_app" in types
assert "main_method" in types
def test_classify_file_main_class(analyzer):
"""Test classification of main class with main method."""
content = """
public class Main {
public static void main(String[] args) {
System.out.println("Hello");
}
}
"""
cluster = analyzer.classify_file("src/main/java/Main.java", content)
assert cluster == "entry_points"
def test_classify_file_spring_boot(analyzer):
"""Test classification of Spring Boot application class."""
content = """
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
"""
cluster = analyzer.classify_file("src/main/java/Application.java", content)
assert cluster == "entry_points"
def test_classify_file_servlet(analyzer):
"""Test classification of servlet class."""
content = """
@WebServlet("/api")
public class ApiServlet extends HttpServlet {
}
"""
cluster = analyzer.classify_file("src/main/java/ApiServlet.java", content)
assert cluster == "entry_points"
def test_classify_file_rest_controller(analyzer):
"""Test classification of REST controller."""
content = """
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List<User> getUsers() {
return userService.findAll();
}
}
"""
cluster = analyzer.classify_file("src/main/java/UserController.java", content)
assert cluster == "core_logic"
def test_classify_file_controller(analyzer):
"""Test classification of MVC controller."""
content = """
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return "index";
}
}
"""
cluster = analyzer.classify_file("src/main/java/HomeController.java", content)
assert cluster == "core_logic"
def test_classify_file_service(analyzer):
"""Test classification of service class."""
content = """
@Service
public class UserService {
public List<User> findAll() {
return repository.findAll();
}
}
"""
cluster = analyzer.classify_file("src/main/java/services/UserService.java", content)
assert cluster == "core_logic"
def test_classify_file_repository(analyzer):
"""Test classification of repository class."""
content = """
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
"""
cluster = analyzer.classify_file(
"src/main/java/repositories/UserRepository.java", content
)
assert cluster == "core_logic"
def test_classify_file_entity(analyzer):
"""Test classification of JPA entity."""
content = """
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
"""
cluster = analyzer.classify_file("src/main/java/entities/User.java", content)
assert cluster == "core_logic"
def test_classify_file_model(analyzer):
"""Test classification of model class by path."""
content = """
public class UserDTO {
private String name;
private String email;
}
"""
cluster = analyzer.classify_file("src/main/java/models/UserDTO.java", content)
assert cluster == "core_logic"
def test_classify_file_dto(analyzer):
"""Test classification of DTO class."""
content = """
public class CreateUserRequest {
private String name;
private String email;
}
"""
cluster = analyzer.classify_file("src/main/java/dto/CreateUserRequest.java", content)
assert cluster == "core_logic"
def test_classify_file_configuration(analyzer):
"""Test classification of configuration class."""
content = """
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
"""
cluster = analyzer.classify_file("src/main/java/config/SecurityConfig.java", content)
assert cluster == "config"
def test_classify_file_config_by_name(analyzer):
"""Test classification of config file by naming convention."""
content = """
public class DatabaseConfiguration {
// Database configuration
}
"""
cluster = analyzer.classify_file(
"src/main/java/DatabaseConfiguration.java", content
)
assert cluster == "config"
def test_classify_file_junit_test(analyzer):
"""Test classification of JUnit test class."""
content = """
import org.junit.Test;
import static org.junit.Assert.*;
public class UserServiceTest {
@Test
public void testFindUser() {
assertEquals("expected", "actual");
}
}
"""
cluster = analyzer.classify_file("src/test/java/UserServiceTest.java", content)
assert cluster == "tests"
def test_classify_file_test_by_annotation(analyzer):
"""Test classification by @Test annotation."""
content = """
import org.junit.jupiter.api.Test;
class CalculatorTests {
@Test
void testAddition() {
// test code
}
}
"""
cluster = analyzer.classify_file("src/test/java/CalculatorTests.java", content)
assert cluster == "tests"
def test_classify_file_testng(analyzer):
"""Test classification of TestNG test class."""
content = """
import org.testng.annotations.Test;
public class IntegrationTest {
@Test
public void testApi() {
// test code
}
}
"""
cluster = analyzer.classify_file("src/test/java/IntegrationTest.java", content)
assert cluster == "tests"
def test_classify_file_test_prefix(analyzer):
"""Test classification by 'Test' prefix in class name."""
content = """
public class TestUtils {
// Test utilities
}
"""
# Base class classifies "Utils" as utilities, which takes precedence
# This is actually correct - TestUtils is more likely utilities than tests
cluster = analyzer.classify_file("src/test/java/TestUtils.java", content)
assert cluster in ("tests", "utilities") # Either is acceptable
def test_should_analyze_normal_files(analyzer):
"""Test that normal Java files should be analyzed."""
assert analyzer.should_analyze("src/main/java/Main.java") == True
assert analyzer.should_analyze("src/main/java/com/example/User.java") == True
assert analyzer.should_analyze("src/test/java/UserTest.java") == True
def test_extract_imports_comprehensive(analyzer):
"""Test comprehensive import extraction with real-world patterns."""
content = """
package com.example.demo;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.*;
import java.nio.file.*;
import static org.junit.Assert.*;
import static java.util.Collections.emptyList;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import com.example.models.User;
import com.example.services.*;
"""
imports = analyzer.extract_imports("Application.java", content)
# Should extract all imports (12 total: 3 regular, 2 wildcard, 2 static, 5 Spring/custom)
assert len(imports) == 12
# Check regular imports
assert any(imp.target_module == "java.util.List" for imp in imports)
assert any(imp.target_module == "java.util.ArrayList" for imp in imports)
# Check wildcard imports
wildcard_imports = [imp for imp in imports if imp.import_type == "wildcard"]
assert len(wildcard_imports) >= 3
assert any(imp.target_module == "java.io.*" for imp in wildcard_imports)
assert any(imp.target_module == "java.nio.file.*" for imp in wildcard_imports)
assert any(imp.target_module == "com.example.services.*" for imp in wildcard_imports)
# Check static imports
static_imports = [imp for imp in imports if imp.import_type == "static"]
assert len(static_imports) >= 2
assert any(
imp.target_module == "org.junit.Assert.*" for imp in static_imports
)
assert any(
imp.target_module == "java.util.Collections.emptyList" for imp in static_imports
)
# Check Spring imports
assert any(
imp.target_module == "org.springframework.boot.SpringApplication"
for imp in imports
)
def test_find_entry_points_comprehensive(analyzer):
"""Test comprehensive entry point detection in realistic file."""
content = """
package com.example.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
@SpringBootApplication
@RestController
@RequestMapping("/api")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@GetMapping("/health")
public String health() {
return "OK";
}
}
"""
entry_points = analyzer.find_entry_points("Application.java", content)
# Should find: @SpringBootApplication, @RestController, main method
assert len(entry_points) >= 3
types = {ep.type for ep in entry_points}
assert "spring_boot_app" in types
assert "rest_controller" in types
assert "main_method" in types
# Verify frameworks
frameworks = {ep.framework for ep in entry_points if ep.framework}
assert "Spring Boot" in frameworks
assert "Spring" in frameworks