<commit_before><?php

declare(strict_types=1);

/*
 * This file is part of composer/satis.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Composer\Satis\Builder;

use Composer\Json\JsonFile;
use Composer\Package\Package;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Output\NullOutput;

/**
 * @author <NAME> <<EMAIL>>
 */
class PackagesBuilderDumpTest extends TestCase
{
    /** @var vfsStreamDirectory */
    protected $package;

    /**
     * @var \org\bovigo\vfs\vfsStreamDirectory
     */
    protected $root;

    protected function setUp(): void
    {
        $this->root = vfsStream::setup('build');
    }

    protected static function createPackages(int $majorVersionNumber, bool $asArray = false)
    {
        $version = $majorVersionNumber . '.0';
        $versionNormalized = $majorVersionNumber . '.0.0.0';
        if ($asArray) {
            return [
                'vendor/name' => [
                    $version => [
                        'name' => 'vendor/name',
                        'version' => $version,
                        'version_normalized' => $versionNormalized,
                        'type' => 'library',
                    ],
                ],
            ];
        }

        return [new Package('vendor/name', $versionNormalized, $version)];
    }

    public function testNominalCase(bool $providers = false)
    {
        $packagesBuilder = new PackagesBuilder(new NullOutput(), vfsStream::url('build'), [
            'providers' => $providers,
            'repositories' => [['type' => 'composer', 'url' => 'http://localhost:54715']],
            'require' => ['vendor/name' => '*'],
        ], false);
        $lastIncludedJsonFile = null;

        foreach ([1, 2, 2] as $i) {
            $packages = self::createPackages($i);
            $arrayPackages = self::createPackages($i, true);

            $packagesBuilder->dump($packages);

            $packagesJson = JsonFile::parseJson($this->root->getChild('build/packages.json')->getContent());
            $this->assertArrayNotHasKey('notify-batch', $packagesJson);

            if ($providers) {
                $packageName = key($arrayPackages);
                $arrayPackages[$packageName][$i . '.0']['uid'] = 1;
                $hash = current($packagesJson['providers'][$packageName]);
                $includeJson = str_replace(['%package%', '%hash%'], [$packageName, $hash], $packagesJson['providers-url']);
            } else {
                $includes = array_keys($packagesJson['includes']);
                $includeJson = end($includes);
            }

            $includeJsonFile = 'build/' . $includeJson;
            $this->assertTrue(is_file(vfsStream::url($includeJsonFile)));

            $packagesIncludeJson = JsonFile::parseJson($this->root->getChild($includeJsonFile)->getContent());
            $this->assertEquals($arrayPackages, $packagesIncludeJson['packages']);

            if ($lastIncludedJsonFile && $lastIncludedJsonFile !== $includeJsonFile) {
                $this->assertFalse(is_file(vfsStream::url($lastIncludedJsonFile)), 'Previous files not pruned');
            }

            $lastIncludedJsonFile = $includeJsonFile;
        }
    }

    public function testProviders()
    {
        $this->testNominalCase(true);
    }

    public function testProvidersUrl()
    {
        $urlToBaseUrlMap = [<commit_msg>Add tests on composer-2.0 format<commit_after><?php

declare(strict_types=1);

/*
 * This file is part of composer/satis.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Composer\Satis\Builder;

use Composer\Json\JsonFile;
use Composer\Package\Package;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Output\NullOutput;

/**
 * @author <NAME> <<EMAIL>@rezo.net>
 */
class PackagesBuilderDumpTest extends TestCase
{
    /** @var vfsStreamDirectory */
    protected $package;

    /**
     * @var \org\bovigo\vfs\vfsStreamDirectory
     */
    protected $root;

    protected function setUp(): void
    {
        $this->root = vfsStream::setup('build');
    }

    protected static function createPackages(int $majorVersionNumber, bool $asArray = false)
    {
        $version = $majorVersionNumber . '.0';
        $versionNormalized = $majorVersionNumber . '.0.0.0';
        if ($asArray) {
            return [
                'vendor/name' => [
                    $version => [
                        'name' => 'vendor/name',
                        'version' => $version,
                        'version_normalized' => $versionNormalized,
                        'type' => 'library',
                    ],
                ],
            ];
        }

        return [new Package('vendor/name', $versionNormalized, $version)];
    }

    public function testNominalCase(bool $providers = false, bool $composer20 = false)
    {
        $packagesBuilder = new PackagesBuilder(new NullOutput(), vfsStream::url('build'), [
            'providers' => $providers,
            'composer-2.0' => $composer20,
            'repositories' => [['type' => 'composer', 'url' => 'http://localhost:54715']],
            'require' => ['vendor/name' => '*'],
        ], false);
        $lastIncludedJsonFile = null;

        foreach ([1, 2, 2] as $i) {
            $packages = self::createPackages($i);
            $arrayPackages = self::createPackages($i, true);

            $packagesBuilder->dump($packages);

            $packagesJson = JsonFile::parseJson($this->root->getChild('build/packages.json')->getContent());
            $this->assertArrayNotHasKey('notify-batch', $packagesJson);

            if ($providers) {
                $packageName = key($arrayPackages);
                $arrayPackages[$packageName][$i . '.0']['uid'] = 1;
                $hash = current($packagesJson['providers'][$packageName]);
                $includeJson = str_replace(['%package%', '%hash%'], [$packageName, $hash], $packagesJson['providers-url']);
            } else {
                $includes = array_keys($packagesJson['includes']);
                $includeJson = end($includes);
            }

            $includeJsonFile = 'build/' . $includeJson;
            $this->assertTrue(is_file(vfsStream::url($includeJsonFile)));

            $packagesIncludeJson = JsonFile::parseJson($this->root->getChild($includeJsonFile)->getContent());
            $this->assertEquals($arrayPackages, $packagesIncludeJson['packages']);

            if ($lastIncludedJsonFile && $lastIncludedJsonFile !== $includeJsonFile) {
                $this->assertFalse(is_file(vfsStream::url($lastIncludedJsonFile)), 'Previous files not pruned');
            }

            $lastIncludedJsonFile = $includeJsonFile;

            if ($composer20) {
                $this->assertArrayHasKey('metadata-url', $packagesJson);
                $packageName = key($arrayPackages);
                foreach (['', '~dev'] as $suffix) {
                    $includeJson = str_replace('%package%', $packageName.$suffix, $packagesJson['metadata-url']);
                    $includeJsonFile = 'build/' . $includeJson;
                    $this->assertTrue(is_file(vfsStream::url($includeJsonFile)), $includeJsonFile.' file must be created');
                }
            } else {
                $this->assertArrayNotHasKey('metadata-url', $packagesJson);
            }
        }
    }

    public function testProviders()
    {
        $this->testNominalCase(true);
    }

    public function testComposer20()
    {
        $this->testNominalCase(false, true);
    }

    public function testProvidersUrl()
    {
        $urlToBaseUrlMap = [
{'fraction_non_alphanumeric': 0.14596350912271933, 'fraction_numerical': 0.005248687828042989, 'mean_word_length': 2.3042939719240296, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 66, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1874771', 'n_tokens_mistral': 2288, 'n_tokens_neox': 2191, 'n_words': 404}