Metadata-Version: 2.4
Name: ft_ps_tester
Version: 1.0.6
Summary: A Python tester for the 42 push_swap project with controlled disorder generation and performance grading.
Author: Italo Almeida
License: MIT
Project-URL: Homepage, https://github.com/italoalmeida0/ft_ps_tester
Project-URL: Issues, https://github.com/italoalmeida0/ft_ps_tester/issues
Keywords: 42,push_swap,tester,sorting,algorithm
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Education :: Testing
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# ft_ps_tester

A Python-based tester for the **42 push_swap** project. It generates controlled random sequences with specific disorder levels, runs your `push_swap` executable, validates the output, and grades performance against 42 thresholds.

---

<img src="https://raw.githubusercontent.com/italoalmeida0/ft_ps_tester/main/i1.jpeg" width="500">
<img src="https://raw.githubusercontent.com/italoalmeida0/ft_ps_tester/main/i2.jpeg" width="500">

---

## Features

- **Controlled disorder generation** — creates sequences with precise inversion percentages.
- **Four test modes** — simple, medium, complex, and adaptive.
- **Output validation** — simulates operations to verify sorting correctness.
- **Performance grading** — compares operation counts against 42 thresholds (excellent / good / pass / fail).
- **Failure report** — concise summary of timeouts, invalid operations, and limit exceedances.
- **Big-O complexity analysis** (`--big-o`) — measures algorithmic scaling across progressively larger inputs with per-mode expectations.

---

## Requirements

- Python 3
- A compiled `push_swap` executable that accepts arguments and prints operations to `stdout`

---

## Installation

> **Tip:** If you run into installation errors, try updating `pip` first:
>
> ```bash
> pip install --upgrade pip
> # or
> pip3 install --upgrade pip
> ```

### Option 1: Install from PyPI (recommended)

Using `pip`:

```bash
pip install ft_ps_tester
```

Using `pip3`:

```bash
pip3 install ft_ps_tester
```

User-local install (no sudo required — `pip`):

```bash
pip install --user ft_ps_tester
```

User-local install (no sudo required — `pip3`):

```bash
pip3 install --user ft_ps_tester
```

Using `python3 -m pip`:

```bash
python3 -m pip install ft_ps_tester
```

> **Note:** When using `--user`, the `ft_ps_tester` binary is installed to a user-local `bin/` directory (e.g. `~/.local/bin` on Linux/macOS, or `%APPDATA%\Python\Python3x\Scripts` on Windows). Make sure this directory is on your `PATH`, or use the `python3 -m` execution methods shown below.

---

### Option 2: Install from source

Clone this repository:

```bash
git clone https://github.com/italoalmeida0/ft_ps_tester.git
cd ft_ps_tester
```

Editable / development mode (`pip`):

```bash
pip install -e .
```

Editable / development mode (`pip3`):

```bash
pip3 install -e .
```

Editable / development mode (`python3 -m pip`):

```bash
python3 -m pip install -e .
```

Normal install (`pip`):

```bash
pip install .
```

Normal install (`pip3`):

```bash
pip3 install .
```

Normal install (`python3 -m pip`):

```bash
python3 -m pip install .
```

User-local install from source (`pip --user`):

```bash
pip install --user -e .
```

User-local install from source (`pip3 --user`):

```bash
pip3 install --user -e .
```

---

### Option 3: Run with `pipx` (isolated, no install required)

If you have [`pipx`](https://pypa.github.io/pipx/) installed, you can run the tester directly without permanently installing it:

```bash
pipx run ft_ps_tester ./push_swap
```

Single test run:

```bash
pipx run ft_ps_tester ./push_swap 500 complex
```

Or install it into an isolated environment:

```bash
pipx install ft_ps_tester
```

Then run normally:

```bash
ft_ps_tester ./push_swap
```

---

Make sure your `push_swap` binary is compiled and executable:

```bash
make
chmod +x push_swap
```

---

## Usage

### Full test suite (recommended)

Tests **100** and **500** elements across all four modes (100 tests each).

If the `ft_ps_tester` command is on your `PATH`:

```bash
ft_ps_tester ./push_swap
```

If the command is **not** found (common with `--user` installs), run via the module:

```bash
python3 -m ft_ps_tester ./push_swap
```

Or using the `.cli` submodule directly:

```bash
python3 -m ft_ps_tester.cli ./push_swap
```

Or using `python` directly:

```bash
python -m ft_ps_tester ./push_swap
```

From the cloned source directory (no install required):

```bash
python3 ft_ps_tester/cli.py ./push_swap
```

---

### Single test run

Test a specific size and mode:

```bash
ft_ps_tester ./push_swap <size> <mode>
```

If `ft_ps_tester` is not on your `PATH`:

```bash
python3 -m ft_ps_tester ./push_swap <size> <mode>
```

Or via the `.cli` submodule:

```bash
python3 -m ft_ps_tester.cli ./push_swap <size> <mode>
```

Example:

```bash
ft_ps_tester ./push_swap 500 complex
```

Or:

```bash
python3 -m ft_ps_tester ./push_swap 500 complex
```

---

### Failure reports (`--reports`)

Enable automatic report generation when a test fails (invalid sort, operation limit exceeded, or timeout). Reports are saved in the **same directory as the `push_swap` executable**.

Two files are generated per failure:

| File suffix   | Content                                  |
| ------------- | ---------------------------------------- |
| `_ops_N.txt`  | Raw output (operations) from `push_swap` |
| `_nums_N.txt` | Input numbers passed to `push_swap`      |

The numbering (`_1`, `_2`, …) is shared between both files: if either an `_ops_N` or `_nums_N` file already exists, the next number is used so both files always share the same suffix.

Example:

```bash
ft_ps_tester --reports ./push_swap
```

If a failure occurs in the `100_simple` test, the following files are created next to `./push_swap`:

```
report_100_simple_ops_1.txt
report_100_simple_nums_1.txt
```

If another failure occurs later (or if one of those files already existed), the next pair becomes:

```
report_100_simple_ops_2.txt
report_100_simple_nums_2.txt
```

You can also use `--reports` with single test runs:

```bash
ft_ps_tester --reports ./push_swap 500 complex
```

---

### Big-O Complexity Analysis (`--big-o`)

Run a dedicated complexity analysis that measures how your algorithm scales with input size. This mode runs **100 tests per size per mode** across progressively larger sequences:

**Sizes tested:** 50, 100, 200, 400, 800

For each size, the tester:

1. Generates sequences with disorder appropriate to the mode
2. Runs **3 warm-up executions** (not measured) to stabilize system caches
3. Runs **100 measured executions** and tracks:
   - **Average number of operations**
   - **Average execution time**
   - **Growth ratio** between consecutive sizes
4. Validates that the output is correctly sorted

If any test fails to sort or times out, the failure is reported and that size/mode combination is marked.

**Classification criteria:**

Both operations and time are classified independently using dynamic formulas based on input size `n`:

**Operations:**

| Complexity     | Formula (max ops)    | Avg growth ratio |
| -------------- | -------------------- | ---------------- |
| `O(n)`         | `1.0 * n`            | ≤ 2.2x           |
| `O(n log n)`   | `1.14 * n * log₂(n)` | ≤ 3.0x           |
| `O(n sqrt(n))` | `1.09 * n * sqrt(n)` | ≤ 3.5x           |
| `O(n²)`        | `0.152 * n²`         | ≤ 4.0x           |
| `O(n³)`        | `0.00095 * n³`       | ≤ 8.0x           |
| `O(>n³)`       | > `0.00095 * n³`     | > 8.0x           |

**Time (ms):**

| Complexity     | Formula (max ms)     | Avg growth ratio |
| -------------- | -------------------- | ---------------- |
| `O(n)`         | `0.05 * n`           | ≤ 2.2x           |
| `O(n log n)`   | `0.08 * n * log₂(n)` | ≤ 3.0x           |
| `O(n sqrt(n))` | `0.12 * n * sqrt(n)` | ≤ 3.5x           |
| `O(n²)`        | `0.25 * n²`          | ≤ 4.0x           |
| `O(n³)`        | `1.0 * n³`           | ≤ 8.0x           |

> **Example:** At n=800, `O(n²)` max ops = `0.152 * 800² ≈ 97,280`. The coefficients are calibrated for push_swap output patterns.

**Expected complexity per mode:**

| Mode       | Expected complexity          | Description                              |
| ---------- | ---------------------------- | ---------------------------------------- |
| `simple`   | ≤ `O(n²)`                    | Nearly sorted — should stay within n²    |
| `medium`   | ≤ `O(n sqrt(n))`             | Moderate disorder — better than n²       |
| `complex`  | `O(n log n)`                 | Heavily shuffled — optimal sort expected |
| `adaptive` | `O(n²)` down to `O(n log n)` | Should adapt based on disorder level     |

**Usage:**

```bash
ft_ps_tester --big-o ./push_swap
```

Or via module:

```bash
python3 -m ft_ps_tester --big-o ./push_swap
```

**Example output:**

```
================================================================================
  BIG-O COMPLEXITY ANALYSIS
================================================================================

>> Big-O Analysis | Mode: SIMPLE
  Size |  Tests |    Avg Ops |  Ops Ratio | Avg Time(ms) | Time Ratio | Status
----------------------------------------------------------------------------------
    50 |    100 |        450 |        N/A |         2.10 |        N/A | PASS
   100 |    100 |        980 |      2.18x |         4.50 |      2.14x | PASS
   ...
----------------------------------------------------------------------------------
Ops Complexity:  O(n^2) (Avg ratio: 3.29x, Max ops at n=800: 75000)
Time Complexity: O(n log n) (Avg ratio: 2.15x, Max time(ms) at n=800: 35.20)

================================================================================
  BIG-O SUMMARY
================================================================================

Mode       | Ops Big-O    | Ops Status | Time Big-O   | Time Status | Overall | Expected
-------------------------------------------------------------------------------------------------------------------
SIMPLE     | O(n log n)   | OK         | O(n^2)       | OK          | PASS    | <= O(n^2)
MEDIUM     | O(n log n)   | OK         | O(n^2)       | FAIL        | FAIL    | <= O(n sqrt(n))
COMPLEX    | O(n log n)   | OK         | O(n^2)       | FAIL        | FAIL    | O(n log n)
ADAPTIVE   | O(n log n)   | OK         | O(n^2)       | OK          | PASS    | O(n^2) down to O(n log n)

Details by mode:
  SIMPLE   | Ops:  Avg ratio: 2.40x, Max ops at n=800: 7732
           | Time: Avg ratio: 3.90x, Max time(ms) at n=800: 206.76
  MEDIUM   | Ops:  Avg ratio: 2.40x, Max ops at n=800: 7732
           | Time: Avg ratio: 3.90x, Max time(ms) at n=800: 206.76
  COMPLEX  | Ops:  Avg ratio: 2.40x, Max ops at n=800: 7732
           | Time: Avg ratio: 3.90x, Max time(ms) at n=800: 206.76
  ADAPTIVE | Ops:  Avg ratio: 2.40x, Max ops at n=800: 7732
           | Time: Avg ratio: 3.90x, Max time(ms) at n=800: 206.76

Reference (Operations & Time):
  Simple  : Expected <= O(n^2)  (nearly sorted)
  Medium  : Expected <= O(n sqrt(n))
  Complex : Expected O(n log n) (optimal comparison sort)
  Adaptive: Expected O(n^2) down to O(n log n) (should adapt to disorder)

Note: Overall PASS requires both Ops and Time to meet expectations.
```

---

## Modes / Flags

Your `push_swap` must support the following flags (passed as `--<mode>` before the numbers):

| Mode       | Disorder range | Description                              |
| ---------- | -------------- | ---------------------------------------- |
| `simple`   | 15.0% – 19.9%  | Nearly sorted sequences                  |
| `medium`   | 20.0% – 49.9%  | Moderately shuffled sequences            |
| `complex`  | 50.0% – 55.0%  | Heavily shuffled sequences               |
| `adaptive` | 15.0% – 55.0%  | Random disorder across the full spectrum |

> **Note:** If your `push_swap` does **not** implement these flags, the tester will still work if your program ignores unknown flags and simply sorts the provided numbers. However, for accurate mode-based testing, your `push_swap` should parse and use the flag to adjust its algorithm.

---

## Grading Thresholds

| Size | Excellent | Good   | Pass    |
| ---- | --------- | ------ | ------- |
| 100  | < 700     | < 1500 | ≤ 2000  |
| 500  | < 5500    | < 8000 | ≤ 12000 |

Results are shown with color-coded grades:

- **EXCELLENT** — green
- **GOOD** — blue
- **PASS** — yellow
- **FAIL** — red

---

## Example Output

```
Running FULL TEST SUITE for ./push_swap

>> Testing Size: 100 | Mode: SIMPLE  ..................................................
>> Testing Size: 100 | Mode: MEDIUM  ..................................................
>> Testing Size: 100 | Mode: COMPLEX ..................................................
>> Testing Size: 100 | Mode: ADAPTIVE..................................................
>> Testing Size: 500 | Mode: SIMPLE  ..................................................
>> Testing Size: 500 | Mode: MEDIUM  ..................................................
>> Testing Size: 500 | Mode: COMPLEX ..................................................
>> Testing Size: 500 | Mode: ADAPTIVE..................................................

========================================================================================
PERFORMANCE SUMMARY
========================================================================================
SIZE   | MODE     | MAX (GRADE)        | MIN (GRADE)        | AVG (GRADE)        | FAILS
----------------------------------------------------------------------------------------
100    | SIMPLE   | 450 (EXCELLENT)    | 320 (EXCELLENT)    | 380 (EXCELLENT)    | 0
100    | MEDIUM   | 1200 (GOOD)        | 900 (EXCELLENT)    | 1050 (GOOD)        | 0
...
```

---

## License

This project is licensed under the [MIT License](LICENSE).
