# retoor <retoor@molodetz.nl>
import pytest
from rp.core.project_analyzer import ProjectAnalyzer, AnalysisResult
class TestProjectAnalyzer:
def setup_method(self):
self.analyzer = ProjectAnalyzer()
def test_analyze_requirements_valid_code(self):
code_content = """
import json
import requests
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=code_content,
)
assert isinstance(result, AnalysisResult)
assert result.language == 'python'
assert 'requests' in result.dependencies
assert 'pydantic' in result.dependencies
def test_pydantic_breaking_change_detection(self):
code_content = """
from pydantic import BaseSettings
class Config(BaseSettings):
api_key: str
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=code_content,
)
assert not result.valid
assert any('BaseSettings' in e for e in result.errors)
def test_shell_command_validation_valid(self):
commands = [
"pip install fastapi",
"mkdir -p /tmp/test",
"python script.py",
]
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
commands=commands,
)
valid_commands = [c for c in result.shell_commands if c['valid']]
assert len(valid_commands) > 0
def test_shell_command_validation_invalid_brace_expansion(self):
commands = [
"mkdir -p {app/{api,database,model)",
]
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
commands=commands,
)
assert not result.valid
assert any('brace' in e.lower() or 'syntax' in e.lower() for e in result.errors)
def test_python_version_detection(self):
code_with_walrus = """
if (x := 10) > 5:
print(x)
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=code_with_walrus,
)
version_parts = result.language_version.split('.')
assert int(version_parts[1]) >= 8
def test_directory_structure_planning(self):
spec_content = """
Create the following structure:
- directory: src/app
- directory: src/tests
- file: src/main.py
- file: src/config.py
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=spec_content,
)
assert len(result.file_structure) > 1
assert '.' in result.file_structure
def test_import_compatibility_check(self):
dependencies = {'pydantic': '2.0', 'fastapi': '0.100'}
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content="",
)
assert isinstance(result.import_compatibility, dict)
def test_token_budget_calculation(self):
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content="import json\nimport requests\n",
commands=["pip install -r requirements.txt"],
)
assert result.estimated_tokens > 0
def test_stdlib_detection(self):
code = """
import os
import sys
import json
import custom_module
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=code,
)
assert 'custom_module' in result.dependencies
assert 'json' not in result.dependencies or len(result.dependencies) == 1
def test_optional_dependencies_detection(self):
code = """
import structlog
import uvicorn
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=code,
)
assert 'structlog' in result.dependencies or len(result.warnings) > 0
def test_fastapi_breaking_change_detection(self):
code = """
from fastapi.middleware.gzip import GZIPMiddleware
"""
result = self.analyzer.analyze_requirements(
spec_file="test.txt",
code_content=code,
)
assert not result.valid
assert any('GZIPMiddleware' in str(e) or 'fastapi' in str(e).lower() for e in result.errors)
class TestCLanguageAnalyzer:
def setup_method(self):
self.analyzer = ProjectAnalyzer()
def test_detect_c_language(self):
c_code = """
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("Hello, World!\\n");
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert result.language == 'c'
def test_c_standard_headers_detection(self):
c_code = """
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert 'stdio.h' in result.dependencies
assert result.dependencies['stdio.h'] == 'stdlib'
assert result.dependencies['math.h'] == 'stdlib'
def test_c_posix_headers_detection(self):
c_code = """
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
int main() {
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert 'unistd.h' in result.dependencies
assert result.dependencies['unistd.h'] == 'posix'
assert any('POSIX' in w for w in result.warnings)
def test_c_local_headers_detection(self):
c_code = """
#include <stdio.h>
#include "myheader.h"
#include "utils/helper.h"
int main() {
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert 'myheader.h' in result.dependencies
assert result.dependencies['myheader.h'] == 'local'
def test_c_external_library_headers(self):
c_code = """
#include <stdio.h>
#include <curl/curl.h>
#include <openssl/ssl.h>
int main() {
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert 'curl/curl.h' in result.dependencies
assert result.dependencies['curl/curl.h'] == 'curl'
assert any('curl' in w for w in result.warnings)
def test_c_standard_detection_c99(self):
c_code = """
#include <stdio.h>
int main() {
for (int i = 0; i < 10; i++) {
printf("%d\\n", i);
}
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert result.language_version == 'c99'
def test_c_standard_detection_c11(self):
c_code = """
#include <stdio.h>
#include <stdatomic.h>
int main() {
_Static_assert(sizeof(int) >= 4, "int must be at least 4 bytes");
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert result.language_version == 'c11'
def test_c_standard_detection_gnu(self):
c_code = """
#include <stdio.h>
int main() {
typeof(5) x = 10;
printf("%d\\n", x);
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert 'gnu' in result.language_version
def test_c_compiler_flags_suggestion(self):
c_code = """
#include <stdio.h>
#include <math.h>
#include <pthread.h>
int main() {
pthread_t thread;
double x = sqrt(2.0);
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert '-lm' in result.compiler_flags
assert '-pthread' in result.compiler_flags
assert any('-std=' in f for f in result.compiler_flags)
assert '-Wall' in result.compiler_flags
def test_c_valid_analysis_no_errors(self):
c_code = """
#include <stdio.h>
int main() {
printf("Hello\\n");
return 0;
}
"""
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
)
assert result.valid
assert len(result.errors) == 0
def test_c_shell_commands_validation(self):
c_code = """
#include <stdio.h>
int main() { return 0; }
"""
commands = [
"gcc -o main main.c",
"make clean",
"./main",
]
result = self.analyzer.analyze_requirements(
spec_file="main.c",
code_content=c_code,
commands=commands,
)
valid_commands = [c for c in result.shell_commands if c['valid']]
assert len(valid_commands) == 3
class TestLanguageDetection:
def setup_method(self):
self.analyzer = ProjectAnalyzer()
def test_detect_python_from_content(self):
python_code = """
def hello():
print("Hello, World!")
if __name__ == "__main__":
hello()
"""
lang = self.analyzer.detect_language(python_code)
assert lang == 'python'
def test_detect_c_from_content(self):
c_code = """
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello\\n");
return 0;
}
"""
lang = self.analyzer.detect_language(c_code)
assert lang == 'c'
def test_detect_cpp_from_content(self):
cpp_code = """
#include <iostream>
int main() {
std::cout << "Hello" << std::endl;
return 0;
}
"""
lang = self.analyzer.detect_language(cpp_code)
assert lang == 'cpp'
def test_detect_rust_from_content(self):
rust_code = """
fn main() {
let x = 5;
println!("x = {}", x);
}
"""
lang = self.analyzer.detect_language(rust_code)
assert lang == 'rust'
def test_detect_go_from_content(self):
go_code = """
package main
import "fmt"
func main() {
fmt.Println("Hello")
}
"""
lang = self.analyzer.detect_language(go_code)
assert lang == 'go'
def test_detect_javascript_from_content(self):
js_code = """
const express = require('express');
function hello() {
console.log("Hello");
}
export default hello;
"""
lang = self.analyzer.detect_language(js_code)
assert lang == 'javascript'
def test_detect_language_from_file_extension(self):
lang = self.analyzer.detect_language("", "main.c")
assert lang == 'c'
lang = self.analyzer.detect_language("", "app.py")
assert lang == 'python'
def test_detect_unknown_language(self):
weird_content = "some random text without any language patterns"
lang = self.analyzer.detect_language(weird_content)
assert lang == 'unknown'