File: SecondLevelCacheManyToManyTest.php

package info (click to toggle)
doctrine 3.5.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 11,552 kB
  • sloc: php: 108,302; xml: 1,340; makefile: 35; sh: 14
file content (246 lines) | stat: -rw-r--r-- 11,842 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\ORM\Cache\Exception\CacheException;
use Doctrine\Tests\Models\Cache\City;
use Doctrine\Tests\Models\Cache\State;
use Doctrine\Tests\Models\Cache\Travel;
use Doctrine\Tests\Models\Cache\Traveler;
use PHPUnit\Framework\Attributes\Group;

#[Group('DDC-2183')]
class SecondLevelCacheManyToManyTest extends SecondLevelCacheFunctionalTestCase
{
    public function testShouldPutManyToManyCollectionOwningSideOnPersist(): void
    {
        $this->evictRegions();

        $this->loadFixturesCountries();
        $this->loadFixturesStates();
        $this->loadFixturesCities();
        $this->loadFixturesTraveler();
        $this->loadFixturesTravels();
        $this->_em->clear();

        self::assertTrue($this->cache->containsEntity(Travel::class, $this->travels[0]->getId()));
        self::assertTrue($this->cache->containsEntity(Travel::class, $this->travels[1]->getId()));

        self::assertTrue($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[0]->getId()));
        self::assertTrue($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[1]->getId()));

        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[0]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[1]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[2]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[3]->getId()));
    }

    public function testPutAndLoadManyToManyRelation(): void
    {
        $this->evictRegions();

        $this->loadFixturesCountries();
        $this->loadFixturesStates();
        $this->loadFixturesCities();
        $this->loadFixturesTraveler();
        $this->loadFixturesTravels();

        $this->_em->clear();
        $this->cache->evictEntityRegion(City::class);
        $this->cache->evictEntityRegion(Travel::class);
        $this->cache->evictCollectionRegion(Travel::class, 'visitedCities');

        $this->secondLevelCacheLogger->clearStats();

        self::assertFalse($this->cache->containsEntity(Travel::class, $this->travels[0]->getId()));
        self::assertFalse($this->cache->containsEntity(Travel::class, $this->travels[1]->getId()));

        self::assertFalse($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[0]->getId()));
        self::assertFalse($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[1]->getId()));

        self::assertFalse($this->cache->containsEntity(City::class, $this->cities[0]->getId()));
        self::assertFalse($this->cache->containsEntity(City::class, $this->cities[1]->getId()));
        self::assertFalse($this->cache->containsEntity(City::class, $this->cities[2]->getId()));
        self::assertFalse($this->cache->containsEntity(City::class, $this->cities[3]->getId()));

        $t1 = $this->_em->find(Travel::class, $this->travels[0]->getId());
        $t2 = $this->_em->find(Travel::class, $this->travels[1]->getId());

        self::assertEquals(2, $this->secondLevelCacheLogger->getPutCount());
        self::assertEquals(2, $this->secondLevelCacheLogger->getMissCount());
        self::assertEquals(2, $this->secondLevelCacheLogger->getRegionPutCount($this->getEntityRegion(Travel::class)));
        self::assertEquals(2, $this->secondLevelCacheLogger->getRegionMissCount($this->getEntityRegion(Travel::class)));

        //trigger lazy load
        self::assertCount(3, $t1->getVisitedCities());
        self::assertCount(2, $t2->getVisitedCities());

        self::assertEquals(4, $this->secondLevelCacheLogger->getPutCount());
        self::assertEquals(4, $this->secondLevelCacheLogger->getMissCount());
        self::assertEquals(2, $this->secondLevelCacheLogger->getRegionPutCount($this->getCollectionRegion(Travel::class, 'visitedCities')));
        self::assertEquals(2, $this->secondLevelCacheLogger->getRegionMissCount($this->getCollectionRegion(Travel::class, 'visitedCities')));

        self::assertInstanceOf(City::class, $t1->getVisitedCities()->get(0));
        self::assertInstanceOf(City::class, $t1->getVisitedCities()->get(1));
        self::assertInstanceOf(City::class, $t1->getVisitedCities()->get(2));

        self::assertInstanceOf(City::class, $t2->getVisitedCities()->get(0));
        self::assertInstanceOf(City::class, $t2->getVisitedCities()->get(1));

        self::assertTrue($this->cache->containsEntity(Travel::class, $this->travels[0]->getId()));
        self::assertTrue($this->cache->containsEntity(Travel::class, $this->travels[1]->getId()));

        self::assertTrue($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[0]->getId()));
        self::assertTrue($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[1]->getId()));

        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[0]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[1]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[2]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[3]->getId()));

        $this->_em->clear();
        $this->secondLevelCacheLogger->clearStats();

        $this->getQueryLog()->reset()->enable();

        $t3 = $this->_em->find(Travel::class, $this->travels[0]->getId());
        $t4 = $this->_em->find(Travel::class, $this->travels[1]->getId());

        //trigger lazy load from cache
        self::assertCount(3, $t3->getVisitedCities());
        self::assertCount(2, $t4->getVisitedCities());

        self::assertInstanceOf(City::class, $t3->getVisitedCities()->get(0));
        self::assertInstanceOf(City::class, $t3->getVisitedCities()->get(1));
        self::assertInstanceOf(City::class, $t3->getVisitedCities()->get(2));

        self::assertInstanceOf(City::class, $t4->getVisitedCities()->get(0));
        self::assertInstanceOf(City::class, $t4->getVisitedCities()->get(1));

        self::assertEquals(4, $this->secondLevelCacheLogger->getHitCount());
        self::assertEquals(2, $this->secondLevelCacheLogger->getRegionHitCount($this->getEntityRegion(Travel::class)));
        self::assertEquals(2, $this->secondLevelCacheLogger->getRegionHitCount($this->getCollectionRegion(Travel::class, 'visitedCities')));

        self::assertNotSame($t1->getVisitedCities()->get(0), $t3->getVisitedCities()->get(0));
        self::assertEquals($t1->getVisitedCities()->get(0)->getId(), $t3->getVisitedCities()->get(0)->getId());
        self::assertEquals($t1->getVisitedCities()->get(0)->getName(), $t3->getVisitedCities()->get(0)->getName());

        self::assertNotSame($t1->getVisitedCities()->get(1), $t3->getVisitedCities()->get(1));
        self::assertEquals($t1->getVisitedCities()->get(1)->getId(), $t3->getVisitedCities()->get(1)->getId());
        self::assertEquals($t1->getVisitedCities()->get(1)->getName(), $t3->getVisitedCities()->get(1)->getName());

        self::assertNotSame($t1->getVisitedCities()->get(2), $t3->getVisitedCities()->get(2));
        self::assertEquals($t1->getVisitedCities()->get(2)->getId(), $t3->getVisitedCities()->get(2)->getId());
        self::assertEquals($t1->getVisitedCities()->get(2)->getName(), $t3->getVisitedCities()->get(2)->getName());

        self::assertNotSame($t2->getVisitedCities()->get(0), $t4->getVisitedCities()->get(0));
        self::assertEquals($t2->getVisitedCities()->get(0)->getId(), $t4->getVisitedCities()->get(0)->getId());
        self::assertEquals($t2->getVisitedCities()->get(0)->getName(), $t4->getVisitedCities()->get(0)->getName());

        self::assertNotSame($t2->getVisitedCities()->get(1), $t4->getVisitedCities()->get(1));
        self::assertEquals($t2->getVisitedCities()->get(1)->getId(), $t4->getVisitedCities()->get(1)->getId());
        self::assertEquals($t2->getVisitedCities()->get(1)->getName(), $t4->getVisitedCities()->get(1)->getName());

        self::assertEquals(4, $this->secondLevelCacheLogger->getHitCount());
        $this->assertQueryCount(0);
    }

    public function testStoreManyToManyAssociationWhitCascade(): void
    {
        $this->evictRegions();

        $this->loadFixturesCountries();
        $this->loadFixturesStates();
        $this->loadFixturesCities();

        $this->cache->evictEntityRegion(City::class);
        $this->cache->evictEntityRegion(Traveler::class);
        $this->cache->evictEntityRegion(Travel::class);
        $this->cache->evictCollectionRegion(State::class, 'cities');
        $this->cache->evictCollectionRegion(Traveler::class, 'travels');

        $traveler = new Traveler('Doctrine Bot');
        $travel   = new Travel($traveler);

        $travel->addVisitedCity($this->cities[0]);
        $travel->addVisitedCity($this->cities[1]);
        $travel->addVisitedCity($this->cities[3]);

        $this->_em->persist($traveler);
        $this->_em->persist($travel);
        $this->_em->flush();
        $this->_em->clear();

        self::assertTrue($this->cache->containsEntity(Travel::class, $travel->getId()));
        self::assertTrue($this->cache->containsEntity(Traveler::class, $traveler->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[0]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[1]->getId()));
        self::assertTrue($this->cache->containsEntity(City::class, $this->cities[3]->getId()));
        self::assertTrue($this->cache->containsCollection(Travel::class, 'visitedCities', $travel->getId()));

        $this->getQueryLog()->reset()->enable();
        $t1 = $this->_em->find(Travel::class, $travel->getId());

        self::assertInstanceOf(Travel::class, $t1);
        self::assertCount(3, $t1->getVisitedCities());
        $this->assertQueryCount(0);
    }

    public function testReadOnlyCollection(): void
    {
        $this->expectException(CacheException::class);

        $this->expectExceptionMessage('Cannot update a readonly collection "Doctrine\Tests\Models\Cache\Travel#visitedCities');
        $this->evictRegions();

        $this->loadFixturesCountries();
        $this->loadFixturesStates();
        $this->loadFixturesCities();
        $this->loadFixturesTraveler();
        $this->loadFixturesTravels();

        $this->_em->clear();

        self::assertTrue($this->cache->containsEntity(Travel::class, $this->travels[0]->getId()));
        self::assertTrue($this->cache->containsCollection(Travel::class, 'visitedCities', $this->travels[0]->getId()));

        $travel = $this->_em->find(Travel::class, $this->travels[0]->getId());

        self::assertCount(3, $travel->getVisitedCities());

        $travel->getVisitedCities()->remove(0);

        $this->_em->persist($travel);
        $this->_em->flush();
    }

    public function testManyToManyWithEmptyRelation(): void
    {
        $this->loadFixturesCountries();
        $this->loadFixturesStates();
        $this->loadFixturesCities();
        $this->loadFixturesTraveler();
        $this->loadFixturesTravels();
        $this->_em->clear();

        $this->evictRegions();

        $this->getQueryLog()->reset()->enable();

        $entitiId = $this->travels[2]->getId(); //empty travel
        $entity   = $this->_em->find(Travel::class, $entitiId);

        self::assertEquals(0, $entity->getVisitedCities()->count());
        $this->assertQueryCount(2);

        $this->_em->clear();

        $entity = $this->_em->find(Travel::class, $entitiId);

        $this->getQueryLog()->reset()->enable();
        self::assertEquals(0, $entity->getVisitedCities()->count());
        $this->assertQueryCount(0);
    }
}