Skip to content

Commit

Permalink
Merge pull request #32 from redthor/fix-get-migrated-timestamp
Browse files Browse the repository at this point in the history
Fix get migrated timestamp
  • Loading branch information
redthor authored Apr 12, 2018
2 parents 1b8fb30 + 5cbeb6a commit 8ace2bb
Show file tree
Hide file tree
Showing 5 changed files with 259 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ public function getMigratedVersions()
* @return string
*
* @throws AntiMattr\MongoDB\Migrations\Exception\UnknownVersionException Throws exception if migration version does not exist
* @throws DomainException If more than one version exists
*/
public function getMigratedTimestamp($version)
{
Expand All @@ -318,14 +319,17 @@ public function getMigratedTimestamp($version)
}

if ($cursor->count() > 1) {
throw \DomainException(
throw new \DomainException(
'Unexpected duplicate version records in the database'
);
}

$returnVersion = $cursor->getNext();

return (string) $returnVersion['t'];
// Convert to normalised timestamp
$ts = new Timestamp($returnVersion['t']);

return (string) $ts;
}

/**
Expand Down
87 changes: 87 additions & 0 deletions src/AntiMattr/MongoDB/Migrations/Configuration/Timestamp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

/*
* This file is part of the AntiMattr MongoDB Migrations Library, a library by Matthew Fitzgerald.
*
* (c) 2014 Matthew Fitzgerald
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace AntiMattr\MongoDB\Migrations\Configuration;

/**
* This class is to normalise the potential values from the 't' version
* attribute.
*
* @author Douglas Reith <[email protected]>
*/
class Timestamp
{
private $t;

/**
* @param mixed $t
*/
public function __construct($t)
{
$this->t = $t;
}

/**
* Normalise based on the different options for backward/forward
* compatibility.
*
* @return int Time in seconds since 1970
*/
public function getTimestamp(): int
{
$supportedClasses = implode(
', ',
[
'\MongoTimestamp',
'\MongoDate',
'\MongoDB\BSON\Timestamp',
'\MongoDB\BSON\UTCDateTime',
'\DateTimeInterface',
]
);

if (!$this->t || !is_object($this->t)) {
throw new \DomainException(
'The timestamp to normalise must be one of ' . $supportedClasses . ' but it is not an object'
);
}

switch (get_class($this->t)) {
case 'MongoTimestamp':
return (int) $this->t->__toString();

case 'MongoDate':
return $this->t->sec;

case 'MongoDB\BSON\Timestamp':
return $this->t->getTimestamp();

case 'MongoDB\BSON\UTCDateTime':
return (int) $this->t->toDateTime()->format('U');
}

if ($this->t instanceof \DateTimeInterface) {
return $this->t->getTimestamp();
}

throw new \DomainException(
'The normalised timestamp must be one of ' . $supportedClasses
);
}

/**
* @return string
*/
public function __toString(): string
{
return (string) $this->getTimestamp();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ public function testGetCollection()
$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->will($this->returnValue($database));
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->will($this->returnValue($expectedCollection));
->willReturn($expectedCollection);

$collection = $this->configuration->getCollection();
$this->assertEquals($expectedCollection, $collection);
Expand All @@ -58,12 +58,12 @@ public function testGetCurrentVersion()
$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->will($this->returnValue($database));
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->will($this->returnValue($collection));
->willReturn($collection);

$cursor = $this->buildMock('Doctrine\MongoDB\Cursor');

Expand All @@ -72,21 +72,21 @@ public function testGetCurrentVersion()
$collection->expects($this->once())
->method('find')
->with($in)
->will($this->returnValue($cursor));
->willReturn($cursor);

$cursor->expects($this->once())
->method('sort')
->with(['v' => -1])
->will($this->returnValue($cursor));
->willReturn($cursor);

$cursor->expects($this->once())
->method('limit')
->with(1)
->will($this->returnValue($cursor));
->willReturn($cursor);

$cursor->expects($this->once())
->method('getNext')
->will($this->returnValue(['v' => '20140822185743']));
->willReturn(['v' => '20140822185743']);

$version = $this->configuration->getCurrentVersion();

Expand All @@ -102,7 +102,7 @@ public function testGetDatabase()
$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->will($this->returnValue($expectedDatabase));
->willReturn($expectedDatabase);

$database = $this->configuration->getDatabase();
$this->assertEquals($expectedDatabase, $database);
Expand All @@ -118,12 +118,12 @@ public function testGetMigratedVersions()
$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->will($this->returnValue($database));
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->will($this->returnValue($collection));
->willReturn($collection);

$foundVersions = [
['v' => 'found1'],
Expand All @@ -137,7 +137,7 @@ public function testGetMigratedVersions()

$collection->expects($this->once())
->method('find')
->will($this->returnValue($foundVersions));
->willReturn($foundVersions);

$versions = $this->configuration->getMigratedVersions();
$this->assertEquals($expectedVersions, $versions);
Expand All @@ -153,22 +153,22 @@ public function testGetNumberOfExecutedMigrations()
$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->will($this->returnValue($database));
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->will($this->returnValue($collection));
->willReturn($collection);

$cursor = $this->buildMock('Doctrine\MongoDB\Cursor');

$collection->expects($this->once())
->method('find')
->will($this->returnValue($cursor));
->willReturn($cursor);

$cursor->expects($this->once())
->method('count')
->will($this->returnValue(2));
->willReturn(2);

$this->assertEquals(2, $this->configuration->getNumberOfExecutedMigrations());
}
Expand Down Expand Up @@ -211,32 +211,30 @@ public function testHasVersionMigrated()
$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->will($this->returnValue($database));
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->will($this->returnValue($collection));
->willReturn($collection);

$version1->expects($this->once())
->method('getVersion')
->will($this->returnValue('found'));
->willReturn('found');

$version2->expects($this->once())
->method('getVersion')
->will($this->returnValue('found2'));

$cursor = $this->buildMock('MongoCursor');
->willReturn('found2');

$collection->expects($this->at(1))
->method('findOne')
->with(['v' => 'found'])
->will($this->returnValue('foo'));
->willReturn('foo');

$collection->expects($this->at(2))
->method('findOne')
->with(['v' => 'found2'])
->will($this->returnValue(null));
->willReturn(null);

$this->assertTrue($this->configuration->hasVersionMigrated($version1));
$this->assertFalse($this->configuration->hasVersionMigrated($version2));
Expand All @@ -258,10 +256,10 @@ public function testGetUnavailableMigratedVersions()
->getMock();
$configuration->expects($this->once())
->method('getMigratedVersions')
->will($this->returnValue(['1', '2']));
->willReturn(['1', '2']);
$configuration->expects($this->once())
->method('getAvailableVersions')
->will($this->returnValue(['2', '3']));
->willReturn(['2', '3']);

$this->assertEquals(['1'], $configuration->getUnavailableMigratedVersions());
}
Expand All @@ -272,6 +270,74 @@ public function testValidate()
self::assertNull($this->configuration->validate());
}

/**
* @expectedException \DomainException
* @expectedExceptionMessage Unexpected duplicate version records in the database
*/
public function testDuplicateInGetMigratedTimestampThrowsException()
{
$this->prepareValidConfiguration();

$collection = $this->buildMock('Doctrine\MongoDB\Collection');
$database = $this->buildMock('Doctrine\MongoDB\Database');

$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->willReturn($collection);

$cursor = $this->buildMock('Doctrine\MongoDB\Cursor');

$collection->expects($this->once())
->method('find')
->willReturn($cursor);

$cursor->expects($this->exactly(2))
->method('count')
->willReturn(2);

$this->configuration->getMigratedTimestamp('1');
}

public function testGetMigratedTimestamp()
{
$this->prepareValidConfiguration();

$collection = $this->buildMock('Doctrine\MongoDB\Collection');
$database = $this->buildMock('Doctrine\MongoDB\Database');

$this->connection->expects($this->once())
->method('selectDatabase')
->with('test_antimattr_migrations')
->willReturn($database);

$database->expects($this->once())
->method('selectCollection')
->with('antimattr_migration_versions_test')
->willReturn($collection);

$cursor = $this->buildMock('Doctrine\MongoDB\Cursor');

$collection->expects($this->once())
->method('find')
->willReturn($cursor);

$cursor->expects($this->exactly(2))
->method('count')
->willReturn(1);

$cursor->expects($this->once())
->method('getNext')
->willReturn(['t' => new \DateTime()]);

$this->assertTrue(is_numeric($this->configuration->getMigratedTimestamp('1')));
}

private function prepareValidConfiguration()
{
$directory = dirname(__DIR__) . '/Resources/Migrations/';
Expand Down
Loading

0 comments on commit 8ace2bb

Please sign in to comment.