<commit_before><?php

namespace CL\LunaCore\Test\Unit\Save;

use CL\LunaCore\Save\Save;
use CL\LunaCore\Repo\Event;
use CL\LunaCore\Repo\LinkOne;
use CL\LunaCore\Repo\LinkMany;
use CL\LunaCore\Repo\AbstractLink;
use CL\LunaCore\Model\State;
use CL\LunaCore\Model\Models;
use CL\LunaCore\Test\AbstractTestCase;
use CL\Util\Objects;
use SplObjectStorage;

class SaveTest extends AbstractTestCase
{
    /**
     * @covers CL\LunaCore\Save\Save::fromObjects
     */
    public function testFromObjects()
    {
        $objects = new SplObjectStorage();
        $objects->attach(new Model());
        $objects->attach(new Model());

        $save = Save::fromObjects($objects);
        $this->assertSame(Objects::toArray($objects), Objects::toArray($save->all()));
    }

    /**
     * @covers CL\LunaCore\Save\Save::addModel
     */
    public function testAddModel()
    {
        $save = new Save();
        $model = new Model();

        $save->addModel($model);

        $this->assertCount(1, $save);
        $this->assertTrue($save->has($model));
    }

    public function dataFilters()
    {
        $models = [
            1 => new Model(null, State::SAVED),
            2 => new Model(null, State::VOID),
            3 => new Model(null, State::PENDING),
            4 => new Model(null, State::DELETED),
            5 => new SoftDeleteModel(['deletedAt' => time()], State::DELETED),
            6 => new SoftDeleteModel(null, State::SAVED),
            7 => new SoftDeleteModel(null, State::PENDING),
            8 => new SoftDeleteModel(null, State::DELETED),
        ];

        return [
            [$models, 'getModelsToDelete', [$models[4], $models[8]]],
        ];
    }

    /**
     * @dataProvider dataFilters
     * @covers CL\LunaCore\Save\Save::getModelsToDelete
     * @covers CL\LunaCore\Save\Save::getModelsToInsert
     * @covers CL\LunaCore\Save\Save::getModelsToUpdate
     */
    public function testFilters($models, $filter, $expected)
    {
        $save = new Save();

        $save->addArray($models);

        $filtered = $save->$filter();

        $this->assertInstanceOf('CL\LunaCore\Model\Models', $filtered);
        $this->assertSame($expected, $filtered->toArray());
    }

    /**
     * @covers CL\LunaCore\Save\Save::add
     */
    public function testAdd()
    {
        $save = new Save();

        $models = [
            new Model(),
            new Model(),
            new Model(),
            new Model(),
            new Model(),
            new Model(),
        ];

        $link1 = new LinkOne(Repo::get()->getRel('one'), $models[1]);
        $link1->set($models[5]);
        $link2 = new LinkMany(Repo::get()->getRel('many'), [$models[2], $models[3]]);
        $link2->remove($models[3]);
        $link2->add($models[4]);

        Repo::get()
            ->addLink($models[0], $link1)
            ->addLink($models[1], $link2);

        $save->add($models[0]);

        $this->assertCount(count($models), $save);

        foreach ($models as $model) {
            $this->assertTrue($save->has($model));
        }
    }

    /**
     * @covers CL\LunaCore\Save\Save::eachLink
     */
    public function testEachLink()
    {
        $save = new Save();

        $model1 = new Model();
        $model2 = new Model();

        $link1 = new LinkOne(Repo::get()->getRel('one'), $model2);
        $link2 = new LinkMany(Repo::get()->getRel('many'), []);

        Repo::get()
            ->addLink($model1, $link1)
            ->addLink($model2, $link2);

        $save->add($model1);

        $i = 0;

        $expected = [
            [$model1, $link1],
            [$model2, $link2]
        ];

        $save->eachLink(function(Model $model, AbstractLink $link) use ($expected, & $i) {
            $this->assertSame($expected[$i][0], $model);
            $this->assertSame($expected[$i][1], $link);
            $i++;
        });
    }

    public function dataRelModifiers()
    {
        return [
            [__NAMESPACE__.'\RelOneDelete', 'delete', 'addFromDeleteRels', true],
            [__NAMESPACE__.'\RelOneInsert', 'insert', 'addFromInsertRels', true],
            [__NAMESPACE__.'\RelOneUpdate', 'update', 'callUpdateRels', false],
        ];
    }

    /**
     * @dataProvider dataRelModifiers
     * @covers CL\LunaCore\Save\Save::addFromDeleteRels
     * @covers CL\LunaCore\Save\Save::addFromInsertRels
     * @covers CL\LunaCore\Save\Save::callUpdateRels
     */
    public function testRelModifiers($relClass, $method, $trigger, $expectAdd)
    {
        $save = new Save();

        $model1 = new Model();
        $model2 = new Model();
        $model3 = new Model();
        $model4 = new Model();
        $model5 = new Model();

        $rel1 = $this->getMock(
            $relClass,
            [$method],
            ['test', Repo::get(), Repo::get()]
        );
        $rel2 = Repo::get()->getRel('one');

        $link1 = new LinkOne($rel1, $model3);
        $link2 = new LinkOne($rel2, $model4);

        Repo::get()
            ->setRels([$rel1])
            ->addLink($model1, $link1)
            ->addLink($model2, $link2);

        $save->add($model1);

        $rel1
            ->expects($this->once())
            ->method($method)
            ->with($this->identicalTo($model1), $this->identicalTo($link1))
            ->will($this->returnValue([$model5]));

        $this->assertFalse($save->has($model5));

        $save->$trigger();

        if ($expectAdd) {
            $this->assertTrue($save->has($model5));
        }
    }

    /**
     * @covers CL\LunaCore\Save\Save::execute
     */
    public function testExecute()
    {
        $save = new Save();

        $repo1 = $this->getMock(
            __NAMESPACE__.'\Repo',
            ['deleteModels', 'insertModels', 'updateModels'],
            [__NAMESPACE__.'\Model']
        );

        $repo2 = $this->getMock(
            __NAMESPACE__.'\SoftDeleteRepo',
            ['deleteModels', 'insertModels', 'updateModels'],
            [__NAMESPACE__.'\SoftDeleteModel']
        );

        Repo::set($repo1);
        SoftDeleteRepo::set($repo2);

        $models = [
            1 => (new Model(['id' => 1], State::SAVED))->setProperties(['name' => 'changed']),
            2 => new Model(['id' => 2], State::VOID),
            3 => new Model(['id' => 3], State::PENDING),
            4 => new Model(['id' => 4], State::DELETED),
            5 => (new SoftDeleteModel(['id' => 5], State::DELETED))->setProperties(['deletedAt' => time()]),
            6 => new SoftDeleteModel(['id' => 6], State::SAVED),
            7 => new SoftDeleteModel(['id' => 7], State::PENDING),
            8 => new SoftDeleteModel(['id' => 8], State::DELETED),
            9 => (new SoftDeleteModel(['id' => 9], State::SAVED))->setProperties(['name' => 'changed']),
        ];

        $this->assertTrue($models[5]->isChanged());
        $this->assertTrue($models[5]->isSoftDeleted());
        $this->assertTrue($models[9]->isChanged());
        $this->assertTrue($models[9]->isSaved());<commit_msg>:exclamation: add some test info for hhvm<commit_after><?php

namespace CL\LunaCore\Test\Unit\Save;

use CL\LunaCore\Save\Save;
use CL\LunaCore\Repo\Event;
use CL\LunaCore\Repo\LinkOne;
use CL\LunaCore\Repo\LinkMany;
use CL\LunaCore\Repo\AbstractLink;
use CL\LunaCore\Model\State;
use CL\LunaCore\Model\Models;
use CL\LunaCore\Test\AbstractTestCase;
use CL\Util\Objects;
use SplObjectStorage;

class SaveTest extends AbstractTestCase
{
    /**
     * @covers CL\LunaCore\Save\Save::fromObjects
     */
    public function testFromObjects()
    {
        $objects = new SplObjectStorage();
        $objects->attach(new Model());
        $objects->attach(new Model());

        $save = Save::fromObjects($objects);
        $this->assertSame(Objects::toArray($objects), Objects::toArray($save->all()));
    }

    /**
     * @covers CL\LunaCore\Save\Save::addModel
     */
    public function testAddModel()
    {
        $save = new Save();
        $model = new Model();

        $save->addModel($model);

        $this->assertCount(1, $save);
        $this->assertTrue($save->has($model));
    }

    public function dataFilters()
    {
        $models = [
            1 => new Model(null, State::SAVED),
            2 => new Model(null, State::VOID),
            3 => new Model(null, State::PENDING),
            4 => new Model(null, State::DELETED),
            5 => new SoftDeleteModel(['deletedAt' => time()], State::DELETED),
            6 => new SoftDeleteModel(null, State::SAVED),
            7 => new SoftDeleteModel(null, State::PENDING),
            8 => new SoftDeleteModel(null, State::DELETED),
        ];

        return [
            [$models, 'getModelsToDelete', [$models[4], $models[8]]],
        ];
    }

    /**
     * @dataProvider dataFilters
     * @covers CL\LunaCore\Save\Save::getModelsToDelete
     * @covers CL\LunaCore\Save\Save::getModelsToInsert
     * @covers CL\LunaCore\Save\Save::getModelsToUpdate
     */
    public function testFilters($models, $filter, $expected)
    {
        $save = new Save();

        $save->addArray($models);

        $filtered = $save->$filter();

        $this->assertInstanceOf('CL\LunaCore\Model\Models', $filtered);
        $this->assertSame($expected, $filtered->toArray());
    }

    /**
     * @covers CL\LunaCore\Save\Save::add
     */
    public function testAdd()
    {
        $save = new Save();

        $models = [
            new Model(),
            new Model(),
            new Model(),
            new Model(),
            new Model(),
            new Model(),
        ];

        $link1 = new LinkOne(Repo::get()->getRel('one'), $models[1]);
        $link1->set($models[5]);
        $link2 = new LinkMany(Repo::get()->getRel('many'), [$models[2], $models[3]]);
        $link2->remove($models[3]);
        $link2->add($models[4]);

        Repo::get()
            ->addLink($models[0], $link1)
            ->addLink($models[1], $link2);

        $save->add($models[0]);

        $this->assertCount(count($models), $save);

        foreach ($models as $model) {
            $this->assertTrue($save->has($model));
        }
    }

    /**
     * @covers CL\LunaCore\Save\Save::eachLink
     */
    public function testEachLink()
    {
        $save = new Save();

        $model1 = new Model();
        $model2 = new Model();

        $link1 = new LinkOne(Repo::get()->getRel('one'), $model2);
        $link2 = new LinkMany(Repo::get()->getRel('many'), []);

        Repo::get()
            ->addLink($model1, $link1)
            ->addLink($model2, $link2);

        $save->add($model1);

        $i = 0;

        $expected = [
            [$model1, $link1],
            [$model2, $link2]
        ];

        $save->eachLink(function(Model $model, AbstractLink $link) use ($expected, & $i) {
            $this->assertSame($expected[$i][0], $model);
            $this->assertSame($expected[$i][1], $link);
            $i++;
        });
    }

    public function dataRelModifiers()
    {
        return [
            [__NAMESPACE__.'\RelOneDelete', 'delete', 'addFromDeleteRels', true],
            [__NAMESPACE__.'\RelOneInsert', 'insert', 'addFromInsertRels', true],
            [__NAMESPACE__.'\RelOneUpdate', 'update', 'callUpdateRels', false],
        ];
    }

    /**
     * @dataProvider dataRelModifiers
     * @covers CL\LunaCore\Save\Save::addFromDeleteRels
     * @covers CL\LunaCore\Save\Save::addFromInsertRels
     * @covers CL\LunaCore\Save\Save::callUpdateRels
     */
    public function testRelModifiers($relClass, $method, $trigger, $expectAdd)
    {
        $save = new Save();

        $model1 = new Model();
        $model2 = new Model();
        $model3 = new Model();
        $model4 = new Model();
        $model5 = new Model();

        $rel1 = $this->getMock(
            $relClass,
            [$method],
            ['test', Repo::get(), Repo::get()]
        );
        $rel2 = Repo::get()->getRel('one');

        $link1 = new LinkOne($rel1, $model3);
        $link2 = new LinkOne($rel2, $model4);

        Repo::get()
            ->setRels([$rel1])
            ->addLink($model1, $link1)
            ->addLink($model2, $link2);

        $save->add($model1);

        $rel1
            ->expects($this->once())
            ->method($method)
            ->with($this->identicalTo($model1), $this->identicalTo($link1))
            ->will($this->returnValue([$model5]));

        $this->assertFalse($save->has($model5));

        $save->$trigger();

        if ($expectAdd) {
            $this->assertTrue($save->has($model5));
        }
    }

    /**
     * @covers CL\LunaCore\Save\Save::execute
     */
    public function testExecute()
    {
        $save = new Save();

        $repo1 = $this->getMock(
            __NAMESPACE__.'\Repo',
            ['deleteModels', 'insertModels', 'updateModels'],
            [__NAMESPACE__.'\Model']
        );

        $repo2 = $this->getMock(
            __NAMESPACE__.'\SoftDeleteRepo',
            ['deleteModels', 'insertModels', 'updateModels'],
            [__NAMESPACE__.'\SoftDeleteModel']
        );

        Repo::set($repo1);
        SoftDeleteRepo::set($repo2);

        $models = [
            1 => (new Model(['id' => 1], State::SAVED))->setProperties(['name' => 'changed']),
            2 => new Model(['id' => 2], State::VOID),
            3 => new Model(['id' => 3], State::PENDING),
            4 => new Model(['id' => 4], State::DELETED),
            5 => (new SoftDeleteModel(['id' => 5], State::DELETED))->setProperties(['deletedAt' => time()]),
            6 => new SoftDeleteModel(['id' => 6], State::SAVED),
            7 => new SoftDeleteModel(['id' => 7], State::PENDING),
            8 => new SoftDeleteModel(['id' => 8], State::DELETED),
            9 => (new SoftDeleteModel(['id' => 9], State::SAVED))->setProperties(['name' => 'changed']),
        ];

        var_dump((new SoftDeleteModel(['id' => 5], State::DELETED)));
        var_dump((new SoftDeleteModel(['id' => 5], State::DELETED))->setProperties(['deletedAt' => time()]));
        var_dump($models[5]);


        $this->assertTrue($models[5]->isChanged());
        $this->assertTrue($models[5]->isSoftDeleted());
        $this->assertTrue($models[9]->isChanged());
        $this->assertTrue($models[9]->isSaved());
{'fraction_non_alphanumeric': 0.1851177130044843, 'fraction_numerical': 0.013522982062780268, 'mean_word_length': 2.2052548843476307, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 195, 'https://': 0, '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': '4418942', 'n_tokens_mistral': 4497, 'n_tokens_neox': 4448, 'n_words': 765}