Forráskód Böngészése

Map types from ext-mongo to ext-mongodb

Andreas Braun 10 éve
szülő
commit
e2cf375730

+ 4 - 4
lib/Alcaeus/MongoDbAdapter/TypeConverter.php

@@ -26,7 +26,7 @@ class TypeConverter
         $result = new \stdClass();
 
         foreach ($array as $key => $value) {
-            $result->$key = (is_array($value)) ? static::convertLegacyArrayToObject($value) : static::convertToModernType($value);
+            $result->$key = (is_array($value)) ? static::convertLegacyArrayToObject($value) : static::convertToBSONType($value);
         }
 
         return $result;
@@ -55,11 +55,11 @@ class TypeConverter
         }
     }
 
-    public static function convertToModernType($value)
+    public static function convertToBSONType($value)
     {
         switch (true) {
-            case $value instanceof \MongoId:
-                return $value->getObjectID();
+            case $value instanceof TypeInterface:
+                return $value->toBSONType();
 
             default:
                 return $value;

+ 28 - 0
lib/Alcaeus/MongoDbAdapter/TypeInterface.php

@@ -0,0 +1,28 @@
+<?php
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Alcaeus\MongoDbAdapter;
+
+use MongoDB\BSON\Type;
+
+interface TypeInterface
+{
+    /**
+     * Converts the type to the corresponding BSON type
+     *
+     * @return mixed
+     */
+    public function toBSONType();
+}

+ 33 - 5
lib/Mongo/MongoBinData.php

@@ -13,7 +13,12 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoBinData {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+use MongoDB\BSON\Binary;
+use MongoDB\BSON\Type;
+
+class MongoBinData implements TypeInterface
+{
     /**
      * Generic binary data.
      * @link http://php.net/manual/en/class.mongobindata.php#mongobindata.constants.custom
@@ -70,7 +75,6 @@ class MongoBinData {
      */
     public $type;
 
-
     /**
      * Creates a new binary data object.
      *
@@ -79,11 +83,35 @@ class MongoBinData {
      * @param int $type Data type
      * @return MongoBinData Returns a new binary data object
      */
-    public function __construct($data, $type = 2) {}
+    public function __construct($data, $type = 2)
+    {
+        if ($data instanceof Binary) {
+            $this->bin = $data->getData();
+            $this->type = $data->getType();
+        } else {
+            $this->bin = $data;
+            $this->type = $type;
+        }
+    }
 
     /**
-     * Returns the string representation of this binary data object.
+     * Returns the string "<Mongo Binary Data>". To access the contents of a MongoBinData, use the bin field.
+     *
      * @return string
      */
-    public function __toString() {}
+    public function __toString()
+    {
+        return '<Mongo Binary Data>';
+    }
+
+    /**
+     * Converts this MongoBinData to the new BSON Binary type
+     *
+     * @return Binary
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return new Binary($this->bin, $this->type);
+    }
 }

+ 15 - 10
lib/Mongo/MongoCode.php

@@ -13,30 +13,35 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoCode {
+class MongoCode
+{
     /**
-     * @var $code
+     * @var string
      */
-    public $code;
+    private $code;
 
     /**
-     * @var $scope
+     * @var array
      */
-    public $scope;
+    private $scope;
 
     /**
-     * .
-     *
      * @link http://php.net/manual/en/mongocode.construct.php
      * @param string $code A string of code
      * @param array $scope The scope to use for the code
-     * @return MongoCode Returns a new code object
      */
-    public function __construct($code, array $scope = array()) {}
+    public function __construct($code, array $scope = [])
+    {
+        $this->code = $code;
+        $this->scope = $scope;
+    }
 
     /**
      * Returns this code as a string
      * @return string
      */
-    public function __toString() {}
+    public function __toString()
+    {
+        return $this->code;
+    }
 }

+ 9 - 1
lib/Mongo/MongoCollection.php

@@ -351,7 +351,15 @@ class MongoCollection
      * @param array $fields Fields of the results to return.
      * @return array|null
      */
-    public function findOne(array $query = array(), array $fields = array()) {}
+    public function findOne(array $query = array(), array $fields = array())
+    {
+        $document = $this->collection->findOne(TypeConverter::convertLegacyArrayToObject($query));
+        if ($document !== null) {
+            $document = TypeConverter::convertObjectToLegacyArray($document);
+        }
+
+        return $document;
+    }
 
     /**
      * Creates an index on the given field(s), or does nothing if the index already exists

+ 29 - 4
lib/Mongo/MongoDBRef.php

@@ -13,7 +13,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoDBRef {
+class MongoDBRef
+{
     /**
      * @static
      * @var $refKey
@@ -36,7 +37,19 @@ class MongoDBRef {
      * @param string $database Database name
      * @return array Returns the reference
      */
-    public static function create($collection, $id, $database = null) {}
+    public static function create($collection, $id, $database = null)
+    {
+        $ref = [
+            static::$refKey => $collection,
+            static::$idKey => $id
+        ];
+
+        if ($database !== null) {
+            $ref['$db'] = $database;
+        }
+
+        return $ref;
+    }
 
     /**
      * This not actually follow the reference, so it does not determine if it is broken or not.
@@ -47,7 +60,12 @@ class MongoDBRef {
      * @param mixed $ref Array or object to check
      * @return boolean Returns true if $ref is a reference
      */
-    public static function isRef($ref) {}
+    public static function isRef($ref)
+    {
+        $check = (array) $ref;
+
+        return array_key_exists(static::$refKey, $check) && array_key_exists(static::$idKey, $check);
+    }
 
     /**
      * Fetches the object pointed to by a reference
@@ -57,5 +75,12 @@ class MongoDBRef {
      * @param array $ref Reference to fetch
      * @return array|null Returns the document to which the reference refers or null if the document does not exist (the reference is broken)
      */
-    public static function get($db, $ref) {}
+    public static function get($db, $ref)
+    {
+        if (! static::isRef($ref)) {
+            return null;
+        }
+
+        return $db->selectCollection($ref[static::$refKey])->findOne(['_id' => $ref[static::$idKey]]);
+    }
 }

+ 61 - 6
lib/Mongo/MongoDate.php

@@ -13,7 +13,11 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoDate {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+use MongoDB\BSON\UTCDateTime;
+
+class MongoDate implements TypeInterface
+{
     /**
      * @link http://php.net/manual/en/class.mongodate.php#mongodate.props.sec
      * @var int $sec
@@ -34,18 +38,69 @@ class MongoDate {
      * @param int $usec Microseconds
      * @return MongoDate Returns this new date
      */
-    public function __construct($sec = 0, $usec = 0) {}
+    public function __construct($sec = 0, $usec = 0)
+    {
+        if (func_num_args() == 0) {
+            $time = microtime(true);
+            $sec = floor($time);
+            $usec = ($time - $sec) * 1000000.0;
+        } elseif ($sec instanceof UTCDateTime) {
+            $msecString = (string) $sec;
+
+            $sec = (int) substr($msecString, 0, -3);
+            $usec = ((int) substr($msecString, -3)) * 1000;
+        }
+
+        $this->sec = $sec;
+        $this->usec = $this->truncateMicroSeconds($usec);
+    }
+
+    /**
+     * Returns a string representation of this date
+     * @return string
+     */
+    public function __toString()
+    {
+        return (string) sprintf('%.8f', $this->truncateMicroSeconds($this->usec) / 1000000) . ' ' . $this->sec;
+    }
+
+    /**
+     * Converts this MongoDate to the new BSON UTCDateTime type
+     *
+     * @return UTCDateTime
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        $milliSeconds = ($this->sec * 1000) + ($this->truncateMicroSeconds($this->usec) / 1000);
+
+        return new UTCDateTime($milliSeconds);
+    }
 
     /**
      * Returns a DateTime object representing this date
      * @link http://php.net/manual/en/mongodate.todatetime.php
      * @return DateTime
      */
-    public function toDateTime() {}
+    public function toDateTime()
+    {
+        $datetime = new \DateTime();
+        $datetime->setTimestamp($this->sec);
+
+        $microSeconds = $this->truncateMicroSeconds($this->usec);
+        if ($microSeconds > 0) {
+            $datetime = \DateTime::createFromFormat('Y-m-d H:i:s.u', $datetime->format('Y-m-d H:i:s') . '.' . $microSeconds);
+        }
+
+        return $datetime;
+    }
 
     /**
-     * Returns a string representation of this date
-     * @return string
+     * @param int $usec
+     * @return int
      */
-    public function __toString() {}
+    private function truncateMicroSeconds($usec)
+    {
+        return (int) floor($usec / 1000) * 1000;
+    }
 }

+ 6 - 4
lib/Mongo/MongoId.php

@@ -13,9 +13,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+use Alcaeus\MongoDbAdapter\TypeInterface;
 use MongoDB\BSON\ObjectID;
 
-class MongoId implements Serializable
+class MongoId implements Serializable, TypeInterface
 {
     /*
      * @var ObjectID
@@ -66,11 +67,12 @@ class MongoId implements Serializable
     }
 
     /**
-     * Returns the ObjectID used internally
+     * Converts this MongoId to the new BSON ObjectID type
+     *
      * @return ObjectID
-     * @internal This method is not part of the ext-mongo API. Do not use this!
+     * @internal This method is not part of the ext-mongo API
      */
-    public function getObjectID()
+    public function toBSONType()
     {
         return $this->objectID;
     }

+ 24 - 5
lib/Mongo/MongoInt32.php

@@ -13,24 +13,43 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoInt32 {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+
+class MongoInt32 implements TypeInterface
+{
     /**
      * @link http://php.net/manual/en/class.mongoint32.php#mongoint32.props.value
-     * @var $value
+     * @var string
      */
     public $value;
 
-
     /**
      * Creates a new 32-bit number with the given value.
      *
      * @link http://php.net/manual/en/mongoint32.construct.php
      * @param string $value A number
      */
-    public function __construct($value) {}
+    public function __construct($value)
+    {
+        $this->value = (string) $value;
+    }
 
     /**
      * @return string
      */
-    public function __toString() {}
+    public function __toString()
+    {
+        return (string) $this->value;
+    }
+
+    /**
+     * Converts this MongoInt32 to a native integer
+     *
+     * @return int
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return (int) $this->value;
+    }
 }

+ 24 - 5
lib/Mongo/MongoInt64.php

@@ -13,24 +13,43 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoInt64 {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+
+class MongoInt64 implements TypeInterface
+{
     /**
      * @link http://php.net/manual/en/class.mongoint64.php#mongoint64.props.value
-     * @var $value
+     * @var string
      */
     public $value;
 
-
     /**
      * Creates a new 64-bit number with the given value.
      *
      * @link http://php.net/manual/en/mongoint64.construct.php
      * @param string $value A number
      */
-    public function __construct($value) {}
+    public function __construct($value)
+    {
+        $this->value = (string) $value;
+    }
 
     /**
      * @return string
      */
-    public function __toString() {}
+    public function __toString()
+    {
+        return (string) $this->value;
+    }
+
+    /**
+     * Converts this MongoInt64 to a native integer
+     *
+     * @return int
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return (int) $this->value;
+    }
 }

+ 15 - 1
lib/Mongo/MongoMaxKey.php

@@ -13,5 +13,19 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoMaxKey {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+use MongoDB\BSON\MaxKey;
+
+class MongoMaxKey implements TypeInterface
+{
+    /**
+     * Converts this to the new BSON MaxKey type
+     *
+     * @return MaxKey
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return new MaxKey();
+    }
 }

+ 15 - 1
lib/Mongo/MongoMinKey.php

@@ -13,5 +13,19 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoMinKey {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+use MongoDB\BSON\MinKey;
+
+class MongoMinKey implements TypeInterface
+{
+    /**
+     * Converts this to the new BSON MinKey type
+     *
+     * @return MinKey
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return new MinKey();
+    }
 }

+ 38 - 8
lib/Mongo/MongoRegex.php

@@ -13,16 +13,18 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoRegex {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+use MongoDB\BSON\Regex;
+
+class MongoRegex implements TypeInterface
+{
     /**
-     * @link http://php.net/manual/en/class.mongoregex.php#mongoregex.props.regex
-     * @var $regex
+     * @var string
      */
     public $regex;
 
     /**
-     * @link http://php.net/manual/en/class.mongoregex.php#mongoregex.props.flags
-     * @var $flags
+     * @var string
      */
     public $flags;
 
@@ -30,14 +32,42 @@ class MongoRegex {
      * Creates a new regular expression.
      *
      * @link http://php.net/manual/en/mongoregex.construct.php
-     * @param string $regex Regular expression string of the form /expr/flags
+     * @param string|Regex $regex Regular expression string of the form /expr/flags
      * @return MongoRegex Returns a new regular expression
      */
-    public function __construct($regex) {}
+    public function __construct($regex)
+    {
+        if ($regex instanceof Regex) {
+            $this->regex = $regex->getPattern();
+            $this->flags = $regex->getFlags();
+            return;
+        }
+
+        if (! preg_match('#^/(.*)/([imxslu]*)$#', $regex, $matches)) {
+            throw new MongoException('invalid regex', 9);
+        }
+
+        $this->regex = $matches[1];
+        $this->flags = $matches[2];
+    }
 
     /**
      * Returns a string representation of this regular expression.
      * @return string This regular expression in the form "/expr/flags".
      */
-    public function __toString() {}
+    public function __toString()
+    {
+        return '/' . $this->regex . '/' . $this->flags;
+    }
+
+    /**
+     * Converts this MongoRegex to the new BSON Regex type
+     *
+     * @return Regex
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return new Regex($this->regex, $this->flags);
+    }
 }

+ 50 - 5
lib/Mongo/MongoTimestamp.php

@@ -13,16 +13,25 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-class MongoTimestamp {
+use Alcaeus\MongoDbAdapter\TypeInterface;
+use MongoDB\BSON\Timestamp;
+
+class MongoTimestamp implements TypeInterface
+{
+    /**
+     * @var int
+     */
+    private static $globalInc = 0;
+
     /**
      * @link http://php.net/manual/en/class.mongotimestamp.php#mongotimestamp.props.sec
-     * @var $sec
+     * @var int
      */
     public $sec;
 
     /**
      * @link http://php.net/manual/en/class.mongotimestamp.php#mongotimestamp.props.inc
-     * @var $inc
+     * @var int
      */
     public $inc;
 
@@ -36,10 +45,46 @@ class MongoTimestamp {
      * @param int $sec [optional] Number of seconds since January 1st, 1970
      * @param int $inc [optional] Increment
      */
-    public function __construct($sec = 0, $inc) {}
+    public function __construct($sec = 0, $inc = 0)
+    {
+        if ($sec instanceof Timestamp) {
+            // Only way is to convert is from string: [<sec>:<inc>]
+            $parts = explode(':', substr((string) $sec, 1, -1));
+            $this->sec = (int) $parts[0];
+            $this->inc = (int) $parts[1];
+
+            return;
+        }
+
+        if (func_num_args() == 0) {
+            $sec = time();
+        }
+
+        if (func_num_args() <= 1) {
+            $inc = static::$globalInc;
+            static::$globalInc++;
+        }
+
+        $this->sec = (int) $sec;
+        $this->inc = (int) $inc;
+    }
 
     /**
      * @return string
      */
-    public function __toString() {}
+    public function __toString()
+    {
+        return (string) $this->sec;
+    }
+
+    /**
+     * Converts this MongoTimestamp to the new BSON Timestamp type
+     *
+     * @return Timestamp
+     * @internal This method is not part of the ext-mongo API
+     */
+    public function toBSONType()
+    {
+        return new Timestamp($this->sec, $this->inc);
+    }
 }

+ 33 - 0
tests/Alcaeus/MongoDbAdapter/MongoBinDataTest.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoBinDataTest extends TestCase
+{
+    public function testCreate()
+    {
+        $bin = new \MongoBinData('foo', \MongoBinData::FUNC);
+        $this->assertAttributeSame('foo', 'bin', $bin);
+        $this->assertAttributeSame(\MongoBinData::FUNC, 'type', $bin);
+
+        $this->assertSame('<Mongo Binary Data>', (string) $bin);
+
+        $bsonBinary = $bin->toBSONType();
+        $this->assertInstanceOf('MongoDB\BSON\Binary', $bsonBinary);
+
+        $this->assertSame('foo', $bsonBinary->getData());
+        $this->assertSame(\MongoDB\BSON\Binary::TYPE_FUNCTION, $bsonBinary->getType());
+    }
+
+    public function testCreateWithBsonBinary()
+    {
+        $bsonBinary = new \MongoDB\BSON\Binary('foo', \MongoDB\BSON\Binary::TYPE_UUID);
+        $bin = new \MongoBinData($bsonBinary);
+
+        $this->assertAttributeSame('foo', 'bin', $bin);
+        $this->assertAttributeSame(\MongoBinData::UUID_RFC4122, 'type', $bin);
+    }
+}

+ 78 - 0
tests/Alcaeus/MongoDbAdapter/MongoDBRefTest.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoDBRefTest extends TestCase
+{
+    public function testCreate()
+    {
+        $id = new \MongoId();
+        $ref = \MongoDBRef::create('foo', $id);
+        $this->assertSame(['$ref' => 'foo', '$id' => $id], $ref);
+    }
+
+    public function testCreateWithDatabase()
+    {
+        $id = new \MongoId();
+        $ref = \MongoDBRef::create('foo', $id, 'database');
+        $this->assertSame(['$ref' => 'foo', '$id' => $id, '$db' => 'database'], $ref);
+    }
+
+    /**
+     * @dataProvider dataIsRef
+     */
+    public function testIsRef($expected, $ref)
+    {
+        $this->assertSame($expected, \MongoDBRef::isRef($ref));
+    }
+
+    public static function dataIsRef()
+    {
+        $objectRef = new \stdClass();
+        $objectRef->{'$ref'} = 'coll';
+        $objectRef->{'$id'} = 'id';
+
+        return [
+            'validRef' => [true, ['$ref' => 'coll', '$id' => 'id']],
+            'validRefWithDatabase' => [true, ['$ref' => 'coll', '$id' => 'id', '$db' => 'db']],
+            'refMissing' => [false, ['$id' => 'id']],
+            'idMissing' => [false, ['$ref' => 'coll']],
+            'objectRef' => [true, $objectRef],
+            'int' => [false, 5],
+        ];
+    }
+
+    public function testGet()
+    {
+        $id = new \MongoId();
+
+        $client = new \MongoClient();
+        $db = $client->selectDB('mongo-php-adapter');
+
+        $document = ['_id' => $id, 'foo' => 'bar'];
+        $db->selectCollection('test')->insert($document);
+
+        $fetchedRef = \MongoDBRef::get($db, ['$ref' => 'test', '$id' => $id]);
+        $this->assertInternalType('array', $fetchedRef);
+        $this->assertEquals($document, $fetchedRef);
+    }
+
+    public function testGetWithNonExistingDocument()
+    {
+        $client = new \MongoClient();
+        $db = $client->selectDB('mongo-php-adapter');
+
+        $this->assertNull(\MongoDBRef::get($db, ['$ref' => 'test', '$id' => 'foo']));
+    }
+
+    public function testGetWithInvalidRef()
+    {
+        $client = new \MongoClient();
+        $db = $client->selectDB('mongo-php-adapter');
+
+        $this->assertNull(\MongoDBRef::get($db, []));
+    }
+}

+ 37 - 0
tests/Alcaeus/MongoDbAdapter/MongoDateTest.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoDateTest extends TestCase
+{
+    public function testCreate()
+    {
+        $date = new \MongoDate(1234567890, 123456);
+        $this->assertAttributeSame(1234567890, 'sec', $date);
+        $this->assertAttributeSame(123000, 'usec', $date);
+
+        $this->assertSame('0.12300000 1234567890', (string) $date);
+        $dateTime = $date->toDateTime();
+
+        $this->assertSame(1234567890, $dateTime->getTimestamp());
+        $this->assertSame('123000', $dateTime->format('u'));
+
+        $bsonDate = $date->toBSONType();
+        $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $bsonDate);
+        $this->assertSame('1234567890123', (string) $bsonDate);
+
+        $this->assertEquals($dateTime, $bsonDate->toDateTime());
+    }
+
+    public function testCreateWithBsonDate()
+    {
+        $bsonDate = new \MongoDB\BSON\UTCDateTime(1234567890123);
+        $date = new \MongoDate($bsonDate);
+
+        $this->assertAttributeSame(1234567890, 'sec', $date);
+        $this->assertAttributeSame(123000, 'usec', $date);
+    }
+}

+ 15 - 0
tests/Alcaeus/MongoDbAdapter/MongoMaxKeyTest.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoMaxKeyTest extends TestCase
+{
+    public function testConvert()
+    {
+        $MaxKey = new \MongoMaxKey();
+        $this->assertInstanceOf('MongoDB\BSON\MaxKey', $MaxKey->toBSONType());
+    }
+}

+ 15 - 0
tests/Alcaeus/MongoDbAdapter/MongoMinKeyTest.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoMinKeyTest extends TestCase
+{
+    public function testConvert()
+    {
+        $minKey = new \MongoMinKey();
+        $this->assertInstanceOf('MongoDB\BSON\MinKey', $minKey->toBSONType());
+    }
+}

+ 32 - 0
tests/Alcaeus/MongoDbAdapter/MongoRegexTest.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoRegexTest extends TestCase
+{
+    public function testCreate()
+    {
+        $regex = new \MongoRegex('/abc/i');
+        $this->assertAttributeSame('abc', 'regex', $regex);
+        $this->assertAttributeSame('i', 'flags', $regex);
+
+        $this->assertSame('/abc/i', (string) $regex);
+
+        $bsonRegex = $regex->toBSONType();
+        $this->assertInstanceOf('MongoDB\BSON\Regex', $bsonRegex);
+        $this->assertSame('abc', $bsonRegex->getPattern());
+        $this->assertSame('i', $bsonRegex->getFlags());
+    }
+
+    public function testCreateWithBsonType()
+    {
+        $bsonRegex = new \MongoDB\BSON\Regex('abc', 'i');
+        $regex = new \MongoRegex($bsonRegex);
+
+        $this->assertAttributeSame('abc', 'regex', $regex);
+        $this->assertAttributeSame('i', 'flags', $regex);
+    }
+}

+ 40 - 0
tests/Alcaeus/MongoDbAdapter/MongoTimestampTest.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace Alcaeus\MongoDbAdapter\Tests;
+
+/**
+ * @author alcaeus <alcaeus@alcaeus.org>
+ */
+class MongoTimestampTest extends TestCase
+{
+    public function testCreate()
+    {
+        $timestamp = new \MongoTimestamp(1234567890, 987654321);
+        $this->assertAttributeSame(1234567890, 'sec', $timestamp);
+        $this->assertAttributeSame(987654321, 'inc', $timestamp);
+
+        $this->assertSame('1234567890', (string) $timestamp);
+
+        $bsonTimestamp = $timestamp->toBSONType();
+        $this->assertInstanceOf('MongoDB\BSON\Timestamp', $bsonTimestamp);
+        $this->assertSame('[1234567890:987654321]', (string) $bsonTimestamp);
+    }
+
+    public function testCreateWithGlobalInc()
+    {
+        $timestamp1 = new \MongoTimestamp(1234567890);
+        $timestamp2 = new \MongoTimestamp(1234567890);
+
+        $this->assertAttributeSame(0, 'inc', $timestamp1);
+        $this->assertAttributeSame(1, 'inc', $timestamp2);
+    }
+
+    public function testCreateWithBsonTimestamp()
+    {
+        $bsonTimestamp = new \MongoDB\BSON\Timestamp(1234567890, 987654321);
+        $timestamp = new \MongoTimestamp($bsonTimestamp);
+
+        $this->assertAttributeSame(1234567890, 'sec', $timestamp);
+        $this->assertAttributeSame(987654321, 'inc', $timestamp);
+    }
+}