| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- import os
- from unittest.mock import patch
- import pytest
- from openhands.runtime.plugins.agent_skills.utils.aider import Linter, LintResult
- @pytest.fixture
- def temp_file(tmp_path):
- # Fixture to create a temporary file
- temp_name = os.path.join(tmp_path, 'lint-test.py')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""def foo():
- print("Hello, World!")
- foo()
- """)
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- @pytest.fixture
- def temp_ruby_file_errors(tmp_path):
- # Fixture to create a temporary file
- temp_name = os.path.join(tmp_path, 'lint-test.rb')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""def foo():
- print("Hello, World!")
- foo()
- """)
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- @pytest.fixture
- def temp_ruby_file_errors_parentheses(tmp_path):
- # Fixture to create a temporary file
- temp_name = os.path.join(tmp_path, 'lint-test.rb')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""def print_hello_world()\n puts 'Hello World'\n""")
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- @pytest.fixture
- def temp_ruby_file_correct(tmp_path):
- # Fixture to create a temporary file
- temp_name = os.path.join(tmp_path, 'lint-test.rb')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""def foo
- puts "Hello, World!"
- end
- foo
- """)
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- @pytest.fixture
- def linter(tmp_path):
- return Linter(root=tmp_path)
- @pytest.fixture
- def temp_typescript_file_errors(tmp_path):
- # Fixture to create a temporary TypeScript file with errors
- temp_name = os.path.join(tmp_path, 'lint-test.ts')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""function foo() {
- console.log("Hello, World!")
- foo()
- """)
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- @pytest.fixture
- def temp_typescript_file_errors_semicolon(tmp_path):
- # Fixture to create a temporary TypeScript file with missing semicolon
- temp_name = os.path.join(tmp_path, 'lint-test.ts')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""function printHelloWorld() {
- console.log('Hello World')
- }""")
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- @pytest.fixture
- def temp_typescript_file_correct(tmp_path):
- # Fixture to create a temporary TypeScript file with correct code
- temp_name = os.path.join(tmp_path, 'lint-test.ts')
- with open(temp_name, 'w', encoding='utf-8') as tmp_file:
- tmp_file.write("""function foo(): void {
- console.log("Hello, World!");
- }
- foo();
- """)
- tmp_file.close()
- yield temp_name
- os.remove(temp_name)
- def test_get_rel_fname(linter, temp_file, tmp_path):
- # Test get_rel_fname method
- rel_fname = linter.get_rel_fname(temp_file)
- assert rel_fname == os.path.relpath(temp_file, tmp_path)
- def test_run_cmd(linter, temp_file):
- # Test run_cmd method with a simple command
- result = linter.run_cmd('echo', temp_file, '')
- assert result is None # echo command should return zero exit status
- def test_set_linter(linter):
- # Test set_linter method
- def custom_linter(fname, rel_fname, code):
- return LintResult(text='Custom Linter', lines=[1])
- linter.set_linter('custom', custom_linter)
- assert 'custom' in linter.languages
- assert linter.languages['custom'] == custom_linter
- def test_py_lint(linter, temp_file):
- # Test py_lint method
- result = linter.py_lint(
- temp_file, linter.get_rel_fname(temp_file), "print('Hello, World!')\n"
- )
- assert result is None # No lint errors expected for this simple code
- def test_py_lint_fail(linter, temp_file):
- # Test py_lint method
- result = linter.py_lint(
- temp_file, linter.get_rel_fname(temp_file), "print('Hello, World!')\n"
- )
- assert result is None
- def test_basic_lint(temp_file):
- from openhands.runtime.plugins.agent_skills.utils.aider.linter import basic_lint
- poorly_formatted_code = """
- def foo()
- print("Hello, World!")
- print("Wrong indent")
- foo(
- """
- result = basic_lint(temp_file, poorly_formatted_code)
- assert isinstance(result, LintResult)
- assert result.text.startswith(f'{temp_file}:2:9')
- assert 2 in result.lines
- def test_basic_lint_fail_returns_text_and_lines(temp_file):
- from openhands.runtime.plugins.agent_skills.utils.aider.linter import basic_lint
- poorly_formatted_code = """
- def foo()
- print("Hello, World!")
- print("Wrong indent")
- foo(
- """
- result = basic_lint(temp_file, poorly_formatted_code)
- assert isinstance(result, LintResult)
- assert result.text.startswith(f'{temp_file}:2:9')
- assert 2 in result.lines
- def test_lint_python_compile(temp_file):
- from openhands.runtime.plugins.agent_skills.utils.aider.linter import (
- lint_python_compile,
- )
- result = lint_python_compile(temp_file, "print('Hello, World!')\n")
- assert result is None
- def test_lint_python_compile_fail_returns_text_and_lines(temp_file):
- from openhands.runtime.plugins.agent_skills.utils.aider.linter import (
- lint_python_compile,
- )
- poorly_formatted_code = """
- def foo()
- print("Hello, World!")
- print("Wrong indent")
- foo(
- """
- result = lint_python_compile(temp_file, poorly_formatted_code)
- assert temp_file in result.text
- assert 1 in result.lines
- def test_lint(linter, temp_file):
- result = linter.lint(temp_file)
- assert result is None
- def test_lint_fail(linter, temp_file):
- # Test lint method
- with open(temp_file, 'w', encoding='utf-8') as lint_file:
- lint_file.write("""
- def foo()
- print("Hello, World!")
- print("Wrong indent")
- foo(
- """)
- errors = linter.lint(temp_file)
- assert errors is not None
- def test_lint_pass_ruby(linter, temp_ruby_file_correct):
- result = linter.lint(temp_ruby_file_correct)
- assert result is None
- def test_lint_fail_ruby(linter, temp_ruby_file_errors):
- errors = linter.lint(temp_ruby_file_errors)
- assert errors is not None
- def test_lint_fail_ruby_no_parentheses(linter, temp_ruby_file_errors_parentheses):
- errors = linter.lint(temp_ruby_file_errors_parentheses)
- assert errors is not None
- def test_lint_pass_typescript(linter, temp_typescript_file_correct):
- if linter.ts_installed:
- result = linter.lint(temp_typescript_file_correct)
- assert result is None
- def test_lint_fail_typescript(linter, temp_typescript_file_errors):
- if linter.ts_installed:
- errors = linter.lint(temp_typescript_file_errors)
- assert errors is not None
- def test_lint_fail_typescript_missing_semicolon(
- linter, temp_typescript_file_errors_semicolon
- ):
- if linter.ts_installed:
- with patch.dict(os.environ, {'ENABLE_AUTO_LINT': 'True'}):
- errors = linter.lint(temp_typescript_file_errors_semicolon)
- assert errors is not None
|