File size: 4,456 Bytes
1b35d41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"""Shared fixtures for Code Migration environment tests."""

from __future__ import annotations

import json
import os
import tempfile
from pathlib import Path
from unittest.mock import MagicMock, patch

import pytest

from code_migration.dataset_loader import Task


# ---------------------------------------------------------------------------
# Sample Task factory
# ---------------------------------------------------------------------------

def make_task(**overrides) -> Task:
    """Create a Task with sensible defaults. Override any field via kwargs."""
    defaults = {
        "repo_name": "test-owner/test-repo",
        "repo_url": "https://github.com/test-owner/test-repo.git",
        "commit_hash": "abc123def456",
        "patch": "--- a.txt\n+++ a.txt\n@@ -1 +1 @@\n-old\n+new\n",
        "test_patch": "",
        "gold_patch": "--- src/main.py\n+++ src/main.py\n@@ -1 +1 @@\n-broken\n+fixed\n",
        "reproduction_target_date": "2020-01-01",
        "reproduction_target_version": "3.8.1",
        "migration_target_date": "2025-07-31",
        "migration_target_version": "3.12.11",
        "dockerfile": (
            "FROM python:3.12.11\nWORKDIR /work\nCOPY . .\n"
            "RUN pip install -r requirements.txt\nCMD [\"python\", \"-m\", \"pytest\"]\n"
        ),
        "version_source": "default",
        "script_source": "requirements.txt",
        "dependency_versions": "numpy==1.26.0\npandas==2.1.0\n",
        "test_type": "pytest",
        "test_files": "tests/test_main.py",
        "test_count": 5,
        "related_modules": "numpy",
        "py_file_count": 10,
        "total_loc_python": 500,
        "difficulty": "Easy",
        "license": "MIT",
    }
    defaults.update(overrides)
    return Task(**defaults)


@pytest.fixture
def sample_task() -> Task:
    """A single sample Task."""
    return make_task()


# ---------------------------------------------------------------------------
# Fixture JSONL file
# ---------------------------------------------------------------------------

def _task_to_dict(task: Task) -> dict:
    """Convert a Task dataclass to a plain dict."""
    from dataclasses import asdict
    return asdict(task)


@pytest.fixture
def fixture_jsonl(tmp_path: Path) -> Path:
    """Write a small JSONL fixture with 3 tasks of varying difficulty."""
    tasks = [
        make_task(repo_name="owner/easy-repo", difficulty="Easy"),
        make_task(repo_name="owner/medium-repo", difficulty="Medium"),
        make_task(repo_name="owner/hard-repo", difficulty="Hard"),
    ]
    jsonl_path = tmp_path / "test_dataset.jsonl"
    with open(jsonl_path, "w") as fh:
        for t in tasks:
            fh.write(json.dumps(_task_to_dict(t)) + "\n")
    return jsonl_path


@pytest.fixture
def malformed_jsonl(tmp_path: Path) -> Path:
    """Write a JSONL file with a malformed line at line 2."""
    good = json.dumps(_task_to_dict(make_task()))
    jsonl_path = tmp_path / "bad_dataset.jsonl"
    with open(jsonl_path, "w") as fh:
        fh.write(good + "\n")
        fh.write("{this is not valid json}\n")
        fh.write(good + "\n")
    return jsonl_path


# ---------------------------------------------------------------------------
# Temp workspace helpers
# ---------------------------------------------------------------------------

@pytest.fixture
def workspace_dir(tmp_path: Path) -> Path:
    """Create a temporary workspace directory mimicking /work structure."""
    ws = tmp_path / "workspace"
    ws.mkdir()
    # Create some sample files
    (ws / "src").mkdir()
    (ws / "src" / "main.py").write_text("print('hello')\n")
    (ws / "tests").mkdir()
    (ws / "tests" / "test_main.py").write_text("def test_one(): pass\n")
    (ws / "setup.py").write_text("from setuptools import setup\nsetup()\n")
    (ws / ".hidden_file").write_text("secret\n")
    (ws / "setup_test-owner__test-repo.sh").write_text("#!/bin/bash\n")
    (ws / "test_test-owner__test-repo.sh").write_text("#!/bin/bash\n")
    return ws


# ---------------------------------------------------------------------------
# Mock subprocess helpers
# ---------------------------------------------------------------------------

@pytest.fixture
def mock_subprocess_run():
    """Patch subprocess.run to prevent real process execution."""
    with patch("subprocess.run") as mock_run:
        mock_run.return_value = MagicMock(
            returncode=0, stdout="", stderr=""
        )
        yield mock_run