Files
Investidor-V2/tests/Unit/CartographyWorkbookAuditTest.php

76 lines
3.6 KiB
PHP

<?php
namespace Tests\Unit;
use App\Services\CartographyWorkbookAudit;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use ZipArchive;
class CartographyWorkbookAuditTest extends TestCase
{
private string $path;
protected function setUp(): void
{
parent::setUp();
$this->path = tempnam(sys_get_temp_dir(), 'gis-test-');
$zip = new ZipArchive;
$zip->open($this->path, ZipArchive::OVERWRITE);
$zip->addFromString('xl/workbook.xml', '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"><sheets><sheet name="Synthetic" sheetId="1" r:id="rId1"/></sheets></workbook>');
$zip->addFromString('xl/_rels/workbook.xml.rels', '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Target="worksheets/sheet1.xml"/></Relationships>');
$zip->addFromString('xl/worksheets/sheet1.xml', '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData><row r="1"><c r="A1" t="inlineStr"><is><t>Private synthetic label</t></is></c></row><row r="2"><c r="A2" t="inlineStr"><is><t>Private synthetic label</t></is></c></row><row r="3"><c r="B3"><f>1+1</f><v>2</v></c><c r="C3"/></row></sheetData></worksheet>');
$zip->close();
}
protected function tearDown(): void
{
unlink($this->path);
parent::tearDown();
}
/** @return array<string, string> */
private function manifest(): array
{
return ['sha256' => hash_file('sha256', $this->path), 'owner' => 'Synthetic owner', 'version' => 'test-1',
'received_at' => '2026-09-28', 'classification' => 'internal', 'inspection_authorization' => 'Synthetic test only'];
}
public function test_audit_quarantines_unknown_crs_and_reports_duplicates_without_copying_source_values(): void
{
$report = (new CartographyWorkbookAudit)->inspect($this->path, $this->manifest());
$this->assertSame(3, $report['rows_inspected']);
$this->assertSame('quarantined', $report['status']);
$this->assertFalse($report['publication_allowed']);
$this->assertSame([], $report['transformations']);
$this->assertSame('duplicate', $report['sheets'][0]['rows'][1]['status']);
$this->assertStringNotContainsString('Private synthetic label', json_encode($report));
$this->assertStringContainsString('formula_not_evaluated', json_encode($report));
$this->assertStringContainsString('original_crs_unknown', json_encode($report));
}
public function test_checksum_mismatch_is_rejected(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('checksum');
(new CartographyWorkbookAudit)->inspect($this->path, [...$this->manifest(), 'sha256' => str_repeat('0', 64)]);
}
public function test_inspection_requires_authorization_evidence(): void
{
$this->expectException(RuntimeException::class);
(new CartographyWorkbookAudit)->inspect($this->path, [...$this->manifest(), 'inspection_authorization' => '']);
}
public function test_xml_entities_are_rejected(): void
{
$zip = new ZipArchive;
$zip->open($this->path);
$zip->addFromString('xl/workbook.xml', '<!DOCTYPE workbook [<!ENTITY x SYSTEM "file:///secret">]><workbook>&x;</workbook>');
$zip->close();
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('unsafe');
(new CartographyWorkbookAudit)->inspect($this->path, $this->manifest());
}
}