DatabaseFunctionalTest.php 13.8 KB
Newer Older
1 2 3 4
<?php

namespace MongoDB\Tests\Database;

5
use MongoDB\Database;
6
use MongoDB\Driver\BulkWrite;
7
use MongoDB\Driver\Cursor;
8
use MongoDB\Driver\ReadConcern;
9 10
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\WriteConcern;
11
use MongoDB\Exception\InvalidArgumentException;
12
use MongoDB\Operation\CreateIndexes;
13 14
use function array_key_exists;
use function current;
15

16 17 18 19 20
/**
 * Functional tests for the Database class.
 */
class DatabaseFunctionalTest extends FunctionalTestCase
{
21
    /**
22
     * @dataProvider provideInvalidDatabaseNames
23 24 25
     */
    public function testConstructorDatabaseNameArgument($databaseName)
    {
26
        $this->expectException(InvalidArgumentException::class);
27 28 29 30
        // TODO: Move to unit test once ManagerInterface can be mocked (PHPC-378)
        new Database($this->manager, $databaseName);
    }

31
    public function provideInvalidDatabaseNames()
32
    {
Jeremy Mikola's avatar
Jeremy Mikola committed
33 34 35 36
        return [
            [null],
            [''],
        ];
37 38
    }

39 40 41 42 43
    /**
     * @dataProvider provideInvalidConstructorOptions
     */
    public function testConstructorOptionTypeChecks(array $options)
    {
44
        $this->expectException(InvalidArgumentException::class);
45 46 47 48 49 50 51
        new Database($this->manager, $this->getDatabaseName(), $options);
    }

    public function provideInvalidConstructorOptions()
    {
        $options = [];

52 53 54 55
        foreach ($this->getInvalidReadConcernValues() as $value) {
            $options[][] = ['readConcern' => $value];
        }

56 57 58 59
        foreach ($this->getInvalidReadPreferenceValues() as $value) {
            $options[][] = ['readPreference' => $value];
        }

60 61 62 63
        foreach ($this->getInvalidArrayValues() as $value) {
            $options[][] = ['typeMap' => $value];
        }

64 65 66 67 68 69 70
        foreach ($this->getInvalidWriteConcernValues() as $value) {
            $options[][] = ['writeConcern' => $value];
        }

        return $options;
    }

71 72 73 74 75
    public function testGetManager()
    {
        $this->assertSame($this->manager, $this->database->getManager());
    }

76 77 78 79 80 81 82 83 84 85
    public function testToString()
    {
        $this->assertEquals($this->getDatabaseName(), (string) $this->database);
    }

    public function getGetDatabaseName()
    {
        $this->assertEquals($this->getDatabaseName(), $this->database->getDatabaseName());
    }

86 87 88
    public function testCommand()
    {
        $command = ['isMaster' => 1];
89 90 91 92 93
        $options = [
            'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
        ];

        $cursor = $this->database->command($command, $options);
94

95
        $this->assertInstanceOf(Cursor::class, $cursor);
96 97 98
        $commandResult = current($cursor->toArray());

        $this->assertCommandSucceeded($commandResult);
99
        $this->assertObjectHasAttribute('ismaster', $commandResult);
100 101 102
        $this->assertTrue($commandResult->ismaster);
    }

103 104 105 106 107 108 109 110 111 112
    public function testCommandAppliesTypeMapToCursor()
    {
        $command = ['isMaster' => 1];
        $options = [
            'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
            'typeMap' => ['root' => 'array'],
        ];

        $cursor = $this->database->command($command, $options);

113
        $this->assertInstanceOf(Cursor::class, $cursor);
114 115 116
        $commandResult = current($cursor->toArray());

        $this->assertCommandSucceeded($commandResult);
117
        $this->assertIsArray($commandResult);
118
        $this->assertArrayHasKey('ismaster', $commandResult);
119 120 121
        $this->assertTrue($commandResult['ismaster']);
    }

122 123 124 125 126
    /**
     * @dataProvider provideInvalidDocumentValues
     */
    public function testCommandCommandArgumentTypeCheck($command)
    {
127
        $this->expectException(InvalidArgumentException::class);
128 129 130
        $this->database->command($command);
    }

131 132
    public function testDrop()
    {
133 134 135 136
        $bulkWrite = new BulkWrite();
        $bulkWrite->insert(['x' => 1]);

        $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite);
137 138 139 140 141 142
        $this->assertEquals(1, $writeResult->getInsertedCount());

        $commandResult = $this->database->drop();
        $this->assertCommandSucceeded($commandResult);
        $this->assertCollectionCount($this->getNamespace(), 0);
    }
143

144 145 146 147 148 149 150 151
    public function testGetSelectsCollectionAndInheritsOptions()
    {
        $databaseOptions = ['writeConcern' => new WriteConcern(WriteConcern::MAJORITY)];

        $database = new Database($this->manager, $this->getDatabaseName(), $databaseOptions);
        $collection = $database->{$this->getCollectionName()};
        $debug = $collection->__debugInfo();

152
        $this->assertSame($this->manager, $debug['manager']);
153
        $this->assertSame($this->getDatabaseName(), $debug['databaseName']);
154
        $this->assertSame($this->getCollectionName(), $debug['collectionName']);
155
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
156 157 158
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }

159 160 161 162 163 164 165 166
    public function testModifyCollection()
    {
        $this->database->createCollection($this->getCollectionName());

        $indexes = [['key' => ['lastAccess' => 1], 'expireAfterSeconds' => 3]];
        $createIndexes = new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), $indexes);
        $createIndexes->execute($this->getPrimaryServer());

167 168 169 170 171
        $commandResult = $this->database->modifyCollection(
            $this->getCollectionName(),
            ['index' => ['keyPattern' => ['lastAccess' => 1], 'expireAfterSeconds' => 1000]],
            ['typeMap' => ['root' => 'array', 'document' => 'array']]
        );
172
        $this->assertCommandSucceeded($commandResult);
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

        $commandResult = (array) $commandResult;

        if (array_key_exists('raw', $commandResult)) {
            /* Sharded environment, where we only assert if a shard had a successful update. For
             * non-primary shards that don't have chunks for the collection, the result contains a
             * "ns does not exist" error. */
            foreach ($commandResult['raw'] as $shard) {
                if (array_key_exists('ok', $shard) && $shard['ok'] == 1) {
                    $this->assertSame(3, $shard['expireAfterSeconds_old']);
                    $this->assertSame(1000, $shard['expireAfterSeconds_new']);
                }
            }
        } else {
            $this->assertSame(3, $commandResult['expireAfterSeconds_old']);
            $this->assertSame(1000, $commandResult['expireAfterSeconds_new']);
        }
190 191
    }

192
    public function testSelectCollectionInheritsOptions()
193 194
    {
        $databaseOptions = [
195
            'readConcern' => new ReadConcern(ReadConcern::LOCAL),
196
            'readPreference' => new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED),
197
            'typeMap' => ['root' => 'array'],
198 199 200 201 202 203 204
            'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
        ];

        $database = new Database($this->manager, $this->getDatabaseName(), $databaseOptions);
        $collection = $database->selectCollection($this->getCollectionName());
        $debug = $collection->__debugInfo();

205 206 207
        $this->assertSame($this->manager, $debug['manager']);
        $this->assertSame($this->getDatabaseName(), $debug['databaseName']);
        $this->assertSame($this->getCollectionName(), $debug['collectionName']);
208
        $this->assertInstanceOf(ReadConcern::class, $debug['readConcern']);
209
        $this->assertSame(ReadConcern::LOCAL, $debug['readConcern']->getLevel());
210
        $this->assertInstanceOf(ReadPreference::class, $debug['readPreference']);
211
        $this->assertSame(ReadPreference::RP_SECONDARY_PREFERRED, $debug['readPreference']->getMode());
212
        $this->assertIsArray($debug['typeMap']);
213
        $this->assertSame(['root' => 'array'], $debug['typeMap']);
214
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
215 216 217
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }

218
    public function testSelectCollectionPassesOptions()
219 220
    {
        $collectionOptions = [
221
            'readConcern' => new ReadConcern(ReadConcern::LOCAL),
222
            'readPreference' => new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED),
223
            'typeMap' => ['root' => 'array'],
224 225 226 227 228 229
            'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
        ];

        $collection = $this->database->selectCollection($this->getCollectionName(), $collectionOptions);
        $debug = $collection->__debugInfo();

230
        $this->assertInstanceOf(ReadConcern::class, $debug['readConcern']);
231
        $this->assertSame(ReadConcern::LOCAL, $debug['readConcern']->getLevel());
232
        $this->assertInstanceOf(ReadPreference::class, $debug['readPreference']);
233
        $this->assertSame(ReadPreference::RP_SECONDARY_PREFERRED, $debug['readPreference']->getMode());
234
        $this->assertIsArray($debug['typeMap']);
235
        $this->assertSame(['root' => 'array'], $debug['typeMap']);
236
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
237 238
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    public function testSelectGridFSBucketInheritsOptions()
    {
        $databaseOptions = [
            'readConcern' => new ReadConcern(ReadConcern::LOCAL),
            'readPreference' => new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED),
            'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
        ];

        $database = new Database($this->manager, $this->getDatabaseName(), $databaseOptions);
        $bucket = $database->selectGridFSBucket();
        $debug = $bucket->__debugInfo();

        $this->assertSame($this->manager, $debug['manager']);
        $this->assertSame($this->getDatabaseName(), $debug['databaseName']);
        $this->assertSame('fs', $debug['bucketName']);
        $this->assertSame(261120, $debug['chunkSizeBytes']);
256
        $this->assertInstanceOf(ReadConcern::class, $debug['readConcern']);
257
        $this->assertSame(ReadConcern::LOCAL, $debug['readConcern']->getLevel());
258
        $this->assertInstanceOf(ReadPreference::class, $debug['readPreference']);
259
        $this->assertSame(ReadPreference::RP_SECONDARY_PREFERRED, $debug['readPreference']->getMode());
260
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }

    public function testSelectGridFSBucketPassesOptions()
    {
        $bucketOptions = [
            'bucketName' => 'custom_fs',
            'chunkSizeBytes' => 8192,
            'readConcern' => new ReadConcern(ReadConcern::LOCAL),
            'readPreference' => new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED),
            'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
        ];

        $database = new Database($this->manager, $this->getDatabaseName());
        $bucket = $database->selectGridFSBucket($bucketOptions);
        $debug = $bucket->__debugInfo();

        $this->assertSame($this->getDatabaseName(), $debug['databaseName']);
        $this->assertSame('custom_fs', $debug['bucketName']);
        $this->assertSame(8192, $debug['chunkSizeBytes']);
281
        $this->assertInstanceOf(ReadConcern::class, $debug['readConcern']);
282
        $this->assertSame(ReadConcern::LOCAL, $debug['readConcern']->getLevel());
283
        $this->assertInstanceOf(ReadPreference::class, $debug['readPreference']);
284
        $this->assertSame(ReadPreference::RP_SECONDARY_PREFERRED, $debug['readPreference']->getMode());
285
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
286 287 288
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }

289
    public function testWithOptionsInheritsOptions()
290 291
    {
        $databaseOptions = [
292
            'readConcern' => new ReadConcern(ReadConcern::LOCAL),
293
            'readPreference' => new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED),
294
            'typeMap' => ['root' => 'array'],
295 296 297 298 299 300 301
            'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
        ];

        $database = new Database($this->manager, $this->getDatabaseName(), $databaseOptions);
        $clone = $database->withOptions();
        $debug = $clone->__debugInfo();

302 303
        $this->assertSame($this->manager, $debug['manager']);
        $this->assertSame($this->getDatabaseName(), $debug['databaseName']);
304
        $this->assertInstanceOf(ReadConcern::class, $debug['readConcern']);
305
        $this->assertSame(ReadConcern::LOCAL, $debug['readConcern']->getLevel());
306
        $this->assertInstanceOf(ReadPreference::class, $debug['readPreference']);
307
        $this->assertSame(ReadPreference::RP_SECONDARY_PREFERRED, $debug['readPreference']->getMode());
308
        $this->assertIsArray($debug['typeMap']);
309
        $this->assertSame(['root' => 'array'], $debug['typeMap']);
310
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
311 312 313
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }

314
    public function testWithOptionsPassesOptions()
315 316
    {
        $databaseOptions = [
317
            'readConcern' => new ReadConcern(ReadConcern::LOCAL),
318
            'readPreference' => new ReadPreference(ReadPreference::RP_SECONDARY_PREFERRED),
319
            'typeMap' => ['root' => 'array'],
320 321 322 323 324 325
            'writeConcern' => new WriteConcern(WriteConcern::MAJORITY),
        ];

        $clone = $this->database->withOptions($databaseOptions);
        $debug = $clone->__debugInfo();

326
        $this->assertInstanceOf(ReadConcern::class, $debug['readConcern']);
327
        $this->assertSame(ReadConcern::LOCAL, $debug['readConcern']->getLevel());
328
        $this->assertInstanceOf(ReadPreference::class, $debug['readPreference']);
329
        $this->assertSame(ReadPreference::RP_SECONDARY_PREFERRED, $debug['readPreference']->getMode());
330
        $this->assertIsArray($debug['typeMap']);
331
        $this->assertSame(['root' => 'array'], $debug['typeMap']);
332
        $this->assertInstanceOf(WriteConcern::class, $debug['writeConcern']);
333 334
        $this->assertSame(WriteConcern::MAJORITY, $debug['writeConcern']->getW());
    }
335
}