first commit.

This commit is contained in:
kj
2026-10-05 15:08:39 -03:00
commit b7799f9fff
93 changed files with 8966 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
<?php
use Toolbox\Catalog;
use Toolbox\Manifest;
use Toolbox\Resolver;
use Toolbox\Semver;
use Toolbox\ToolboxException;
Harness::suite('group2');
Harness::it('semver compara y satisface rangos', function () {
ok(Semver::satisfies('1.2.0', '>=1.0'));
ok(!Semver::satisfies('0.9.0', '>=1.0'));
ok(Semver::satisfies('1.2.3', '^1.2'));
ok(!Semver::satisfies('2.0.0', '^1.2'));
ok(Semver::satisfies('1.2.9', '~1.2.3'));
ok(!Semver::satisfies('1.3.0', '~1.2.3'));
ok(Semver::satisfies('1.0.0', '*'));
eq(0, Semver::compare('1.0.0', '1.0.0'));
ok(Semver::compare('1.0.1', '1.0.0') > 0);
ok(Semver::compare('1.0.0-beta', '1.0.0') < 0);
});
Harness::it('manifiesto válido parsea identidad, componentes y default', function () {
$m = Manifest::fromArray([
'name' => 'http',
'version' => '1.2.0',
'description' => 'Utilidades HTTP',
'components' => [
'curlRequest' => ['files' => ['src/Libs/CurlRequest.php']],
'aria2' => ['files' => ['src/Libs/Aria2.php']],
],
'default' => ['curlRequest', 'aria2'],
]);
eq('http', $m->name);
eq('1.2.0', $m->version);
eq(['curlRequest', 'aria2'], $m->expand(null));
eq(['aria2'], $m->expand('aria2'));
});
Harness::it('manifiesto sin name es inválido', function () {
throws(fn () => Manifest::fromArray(['version' => '1.0.0', 'components' => ['a' => ['files' => ['x']]]]));
});
Harness::it('manifiesto sin components es inválido', function () {
throws(fn () => Manifest::fromArray(['name' => 'x', 'version' => '1.0.0']));
});
Harness::it('default que referencia componente inexistente es inválido', function () {
throws(fn () => Manifest::fromArray([
'name' => 'x', 'version' => '1.0.0',
'components' => ['a' => ['files' => ['x']]],
'default' => ['nope'],
]));
});
Harness::it('paquete sin default y sin componente explícito falla', function () {
$m = Manifest::fromArray([
'name' => 'x', 'version' => '1.0.0',
'components' => ['a' => ['files' => ['x']]],
]);
throws(fn () => $m->expand(null));
});
Harness::it('resuelve dependencias en orden (dependencias primero)', function () {
$dir = tmpdir();
write_file($dir . '/http/duckbrain.json', json_encode([
'name' => 'http', 'version' => '1.0.0',
'components' => [
'curlRequest' => ['files' => ['src/Libs/CurlRequest.php']],
'compreFace' => [
'files' => ['src/Libs/CompreFace.php'],
'require' => ['http:curlRequest' => '>=1.0'],
],
],
], JSON_PRETTY_PRINT));
$resolver = new Resolver(new Catalog($dir));
$result = $resolver->resolve(['http:compreFace']);
eq([
['package' => 'http', 'component' => 'curlRequest'],
['package' => 'http', 'component' => 'compreFace'],
], $result);
rrmdir($dir);
});
Harness::it('require no satisfecho detiene con error', function () {
$dir = tmpdir();
write_file($dir . '/a/duckbrain.json', json_encode([
'name' => 'a', 'version' => '1.0.0',
'components' => [
'main' => ['files' => ['src/Libs/A.php'], 'require' => ['b:lib' => '>=2.0']],
],
]));
write_file($dir . '/b/duckbrain.json', json_encode([
'name' => 'b', 'version' => '1.0.0',
'components' => ['lib' => ['files' => ['src/Libs/B.php']]],
]));
$resolver = new Resolver(new Catalog($dir));
throws(fn () => $resolver->resolve(['a:main']));
rrmdir($dir);
});
Harness::it('ciclo de dependencias se detecta', function () {
$dir = tmpdir();
write_file($dir . '/a/duckbrain.json', json_encode([
'name' => 'a', 'version' => '1.0.0',
'components' => [
'x' => ['files' => ['src/Libs/A.php'], 'require' => ['a:y' => '*']],
'y' => ['files' => ['src/Libs/B.php'], 'require' => ['a:x' => '*']],
],
]));
$resolver = new Resolver(new Catalog($dir));
throws(fn () => $resolver->resolve(['a:x']));
rrmdir($dir);
});