diff --git a/.travis.yml b/.travis.yml index eba7303f..a84d8c30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,11 +6,16 @@ php: - 5.3 - 5.4 - 5.5 + - 5.6 + - hhvm + +matrix: + allow_failures: + - php: hhvm before_script: - - "pyrus install pecl/redis && pyrus build pecl/redis" - - "echo \"extension=redis.so\" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini" - - "echo '{\"config\":{\"github-oauth\": {\"github.com\":\"fa354b2f030836334eac842f8fd69a03e353d247\"}}}' > ~/.composer/config.json" - - "composer install --dev --no-progress --no-custom-installers --no-scripts" + - sh -c "if [ \"$TRAVIS_PHP_VERSION\" != \"hhvm\" ]; then pyrus install pecl/redis && pyrus build pecl/redis; fi" + - sh -c "if [ \"$TRAVIS_PHP_VERSION\" != \"hhvm\" ]; then echo \"extension=redis.so\" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi" + - "composer install --no-progress --no-plugins" script: phpunit diff --git a/src/Bernard/Batch.php b/src/Bernard/Batch.php new file mode 100644 index 00000000..01169958 --- /dev/null +++ b/src/Bernard/Batch.php @@ -0,0 +1,70 @@ +name = $name ?: uniqid('bernard_batch', true); + $this->description = $description; + $this->status = $status ?: new Status(0, 0, 0); + } + + public function assign(Message $message) + { + $this->envelopes[] = new Envelope($message, array('batch' => $this->name)); + + $this->status = new Status($this->status->total + 1, $this->status->failed, $this->status->successful); + } + + /** + * Internal method used by the producer to produce the envelopes + * through its mnamedlewares. + * + * @return array + */ + public function flush() + { + $envelopes = $this->envelopes; + $this->envelopes = array(); + + return $envelopes; + } + + public function isRunning() + { + return $this->status->isRunning(); + } + + public function isComplete() + { + return $this->status->isComplete(); + } + + public function getStatus() + { + return $this->status; + } + + public function getDescription() + { + return $this->description; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->name; + } +} diff --git a/src/Bernard/Batch/AbstractStorage.php b/src/Bernard/Batch/AbstractStorage.php new file mode 100644 index 00000000..29ac78fd --- /dev/null +++ b/src/Bernard/Batch/AbstractStorage.php @@ -0,0 +1,16 @@ +find($batch->getName()); + } +} diff --git a/src/Bernard/Batch/RedisStorage.php b/src/Bernard/Batch/RedisStorage.php new file mode 100644 index 00000000..f75c9c3d --- /dev/null +++ b/src/Bernard/Batch/RedisStorage.php @@ -0,0 +1,93 @@ +redis = $redis; + $this->ttl = $ttl ?: 3600 * 36; + } + + /** + * {@inheritDoc} + */ + public function find($name) + { + $result = $this->redis->hmget($this->resolveKey($name), array('total', 'failed', 'successful', 'description')); + + return new Batch($name, $result['description'], new Status($result['total'], $result['failed'], $result['successful'])); + } + + /** + * {@inheritDoc} + */ + public function register($name) + { + $redis = $this->redis->multi(); + + // insert the batch name into the set if dosent exists all ready. + // we use sorted sets to cheat into not really expiring them. + // we update this on last insert into the batch, to make sure we + // dont add message and expire the batch instantanious. + $redis->zadd('batches', $this->ttl + time(), $name); + $redis->incr($this->resolveKey($name, 'total')); + + // create sets with expire at + $redis->expire($this->resolveKey($name, 'total'), $this->ttl); + $redis->expire($this->resolveKey($name, 'failed'), $this->ttl); + $redis->expire($this->resolveKey($name, 'successful'), $this->ttl); + + // fire + $redis->exec(); + } + + /** + * {@inheritDoc} + */ + public function increment($name, $type) + { + if (!in_array($type, array('failed', 'successful'))) { + // should be more precise + throw new \InvalidArgumentException(); + } + + // creates a new key if dosent exists, creates a new field with a + // 0 as default if not exists. + $this->redis->incr($this->resolveKey($name, $type)); + } + + /** + * {@inheritDoc} + */ + public function all() + { + $batches = $this->redis->zrangebyscore('batches', time(), '+inf'); + + return array_map($batches, array($this, 'find')); + } + + /** + * {@inheritDoc} + */ + protected function resolveKey($name, $type = null) + { + return rtrim('batch:' . $name . ':' . $type, ':'); + } +} diff --git a/src/Bernard/Batch/Status.php b/src/Bernard/Batch/Status.php new file mode 100644 index 00000000..0834e82b --- /dev/null +++ b/src/Bernard/Batch/Status.php @@ -0,0 +1,38 @@ +total = $total; + $this->failed = $failed; + $this->successful = $successful; + } + + public function isComplete() + { + return $this->total == $this->failed + $this->successful; + } + + public function isRunning() + { + return false == $this->isComplete(); + } + + public function __get($property) + { + return $this->$property; + } +} diff --git a/src/Bernard/Batch/Storage.php b/src/Bernard/Batch/Storage.php new file mode 100644 index 00000000..2f4117ca --- /dev/null +++ b/src/Bernard/Batch/Storage.php @@ -0,0 +1,50 @@ +message = $message; $this->class = get_class($message); $this->timestamp = time(); + $this->stamps = array_filter($stamps, 'is_scalar'); } /** @@ -55,4 +57,26 @@ public function getTimestamp() { return $this->timestamp; } + + /** + * @return array + */ + public function getStamps() + { + return $this->stamps; + } + + /** + * @param string $name + * @param mixed $default + * @return mixed + */ + public function getStamp($name, $default = null) + { + if (!isset($this->stamps[$name])) { + return $default; + } + + return $this->stamps[$name]; + } } diff --git a/src/Bernard/EventListener/BatchSubscriber.php b/src/Bernard/EventListener/BatchSubscriber.php new file mode 100644 index 00000000..b0659abb --- /dev/null +++ b/src/Bernard/EventListener/BatchSubscriber.php @@ -0,0 +1,48 @@ +storage = $storage; + } + + public function onProduce(EnvelopeEvent $event) + { + $envelope = $event->getEnvelope(); + + if ($batch = $envelope->getStamp('batch')) { + $this->storage->register($envelope->getStamp('batch')); + } + } + + public function onAcknowledgeReject(EnvelopeEvent $event) + { + $envelope = $event->getEnvelope(); + + if (false == $batch = $envelope->getStamp('batch')) { + return; + } + + $type = $event instanceof RejectEnvelopeEvent ? 'failed' : 'successful'; + $this->storage->increment($batch, $type); + } + + public static function getSubscribedEvents() + { + return array( + 'bernard.produce' => 'onProduce', + 'bernard.acknowledge' => 'onAcknowledgeReject', + 'bernard.reject' => 'onAcknowledgeReject', + ); + } +} diff --git a/src/Bernard/JMSSerializer/EnvelopeHandler.php b/src/Bernard/JMSSerializer/EnvelopeHandler.php index c36fabf7..73fb7ee0 100644 --- a/src/Bernard/JMSSerializer/EnvelopeHandler.php +++ b/src/Bernard/JMSSerializer/EnvelopeHandler.php @@ -62,7 +62,7 @@ public function serializeEnvelope(AbstractVisitor $visitor, Envelope $envelope, 'timestamp' => $envelope->getTimestamp(), ); - $visitor->setRoot($data); + $visitor->setRoot($data + $envelope->getStamps()); return $data; } @@ -88,7 +88,9 @@ public function deserializeEnvelope(AbstractVisitor $visitor, array $data, $type $type['name'] = 'Bernard\Message\DefaultMessage'; } - $envelope = new Envelope($context->accept($data['args'], $type)); + $stamps = array_diff_key($data, array_flip(array('timestamp', 'class', 'args'))); + + $envelope = new Envelope($context->accept($data['args'], $type), $stamps); $visitor->setNavigator($context->getNavigator()); diff --git a/src/Bernard/Producer.php b/src/Bernard/Producer.php index 5d23f6e9..ac0361a4 100644 --- a/src/Bernard/Producer.php +++ b/src/Bernard/Producer.php @@ -29,10 +29,21 @@ public function __construct(QueueFactory $queues, EventDispatcherInterface $disp */ public function produce(Message $message, $queueName = null) { - $queueName = $queueName ?: bernard_guess_queue($message); + if ($message instanceof Batch) { + foreach ($message->flush() as $envelope) { + $this->doProduce($envelope, $queueName); + } - $queue = $this->queues->create($queueName); - $queue->enqueue($envelope = new Envelope($message)); + return; + } + + $this->doProduce(new Envelope($message), $queueName); + } + + protected function doProduce(Envelope $envelope, $queueName = null) + { + $queue = $this->queues->create($queueName ?: bernard_guess_queue($envelope->getMessage())); + $queue->enqueue($envelope); $this->dispatcher->dispatch('bernard.produce', new EnvelopeEvent($envelope, $queue)); } diff --git a/src/Bernard/Serializer/SimpleSerializer.php b/src/Bernard/Serializer/SimpleSerializer.php index c901e9f2..88a911c7 100644 --- a/src/Bernard/Serializer/SimpleSerializer.php +++ b/src/Bernard/Serializer/SimpleSerializer.php @@ -24,11 +24,13 @@ public function serialize(Envelope $envelope) $message = $envelope->getMessage(); - return json_encode(array( + $data = array( 'args' => array('name' => $message->getName()) + get_object_vars($message), 'class' => bernard_encode_class_name($envelope->getClass()), 'timestamp' => $envelope->getTimestamp(), - )); + ); + + return json_encode($data + $envelope->getStamps()); } /** @@ -44,7 +46,8 @@ public function deserialize($serialized) $data['args']['name'] = substr(strrchr($class, '\\'), 1); } - $envelope = new Envelope(new DefaultMessage($data['args']['name'], $data['args'])); + $stamps = array_diff_key($data, array_flip(array('timestamp', 'class', 'args'))); + $envelope = new Envelope(new DefaultMessage($data['args']['name'], $data['args']), $stamps); bernard_force_property_value($envelope, 'class', $class); bernard_force_property_value($envelope, 'timestamp', $data['timestamp']); diff --git a/src/Bernard/Symfony/EnvelopeNormalizer.php b/src/Bernard/Symfony/EnvelopeNormalizer.php index 4ff21116..b526c275 100644 --- a/src/Bernard/Symfony/EnvelopeNormalizer.php +++ b/src/Bernard/Symfony/EnvelopeNormalizer.php @@ -20,11 +20,13 @@ class EnvelopeNormalizer extends SerializerAwareNormalizer implements Normalizer */ public function normalize($object, $format = null, array $context = array()) { - return array( + $data = array( 'args' => $this->serializer->normalize($object->getMessage(), $format, $context), 'class' => bernard_encode_class_name($object->getClass()), 'timestamp' => $object->getTimestamp(), ); + + return $data + $object->getStamps(); } /** @@ -37,9 +39,10 @@ public function denormalize($data, $class, $format = null, array $context = arra if (!class_exists($class)) { $class = 'Bernard\\Message\\DefaultMessage'; $data['args']['name'] = substr(strrchr($data['class'], '\\'), 1); - } + } - $envelope = new Envelope($this->serializer->denormalize($data['args'], $class, $format, $context)); + $stamps = array_diff_key($data, array_flip(array('timestamp', 'class', 'args'))); + $envelope = new Envelope($this->serializer->denormalize($data['args'], $class, $format, $context), $stamps); foreach (array('timestamp', 'class') as $name) { bernard_force_property_value($envelope, $name, $data[$name]); diff --git a/tests/Bernard/Tests/Batch/AbstractStorageTest.php b/tests/Bernard/Tests/Batch/AbstractStorageTest.php new file mode 100644 index 00000000..428d94b1 --- /dev/null +++ b/tests/Bernard/Tests/Batch/AbstractStorageTest.php @@ -0,0 +1,16 @@ +getMockForAbstractClass('Bernard\Batch\AbstractStorage'); + $storage->expects($this->once())->method('find')->with('my-id'); + + $storage->reload(new Batch('my-id')); + } +} diff --git a/tests/Bernard/Tests/Batch/RedisStorageTest.php b/tests/Bernard/Tests/Batch/RedisStorageTest.php new file mode 100644 index 00000000..ffa43f05 --- /dev/null +++ b/tests/Bernard/Tests/Batch/RedisStorageTest.php @@ -0,0 +1,96 @@ +markTestSkipped('Missing redis extension.'); + } + + $this->redis = $this->getMock('Redis'); + $this->storage = new RedisStorage($this->redis); + } + + public function testStorage() + { + $this->assertInstanceOf('Bernard\Batch\Storage', $this->storage); + } + + public function testFindReturnsBatch() + { + $this->redis->expects($this->once())->method('hmget') + ->with('batch:my-id', array('total', 'failed', 'successful', 'description')) + ->will($this->returnValue(array('failed' => 2, 'total' => 20, 'successful' => 10, 'description' => 'Info Here...'))); + + $batch = $this->storage->find('my-id'); + + $this->assertEquals('my-id', $batch->getName()); + $this->assertEquals('Info Here...', $batch->getDescription()); + + $this->assertEquals(new Status(20, 2, 10), $batch->getStatus()); + } + + public function testIncrementThrowsExceptionWhenWrongType() + { + $this->setExpectedException('InvalidArgumentException'); + + $this->storage->increment(new Batch(), 'denmark'); + } + + public function testRegister() + { + $storage = new RedisStorage($this->redis, 3600); + + $multi = $this->getMock('Redis', array('expire', 'zadd', 'incr', 'set', 'exec')); + + $this->redis->expects($this->once())->method('multi') + ->will($this->returnValue($multi)); + + $multi->expects($this->at(0))->method('zadd') + ->with('batches', time() + 3600, 'my-name'); + + $multi->expects($this->at(1))->method('incr') + ->with('batch:my-name:total'); + + $multi->expects($this->at(2))->method('expire') + ->with('batch:my-name:total', 3600); + + $multi->expects($this->at(3))->method('expire') + ->with('batch:my-name:failed', 3600); + + $multi->expects($this->at(4))->method('expire') + ->with('batch:my-name:successful', 3600); + + $multi->expects($this->at(5))->method('exec'); + + $storage->register('my-name'); + } + + /** + * @dataProvider incrementProvider + */ + public function testIncrement($type, $key) + { + $this->redis->expects($this->once())->method('incr') + ->with($key); + + $batch = new Batch('my-id'); + + $this->storage->increment($batch->getName(), $type); + } + + public function incrementProvider() + { + return array( + array('successful', 'batch:my-id:successful'), + array('failed', 'batch:my-id:failed'), + ); + } +} diff --git a/tests/Bernard/Tests/Batch/StatusTest.php b/tests/Bernard/Tests/Batch/StatusTest.php new file mode 100644 index 00000000..68231e95 --- /dev/null +++ b/tests/Bernard/Tests/Batch/StatusTest.php @@ -0,0 +1,22 @@ +assertTrue($status->isRunning()); + $this->assertFalse($status->isComplete()); + } + + public function testIsRunning() + { + $status = new Status($total = 10, $failed = 1, $successful = 9); + $this->assertFalse($status->isRunning()); + $this->assertTrue($status->isComplete()); + } +} diff --git a/tests/Bernard/Tests/BatchTest.php b/tests/Bernard/Tests/BatchTest.php new file mode 100644 index 00000000..899b0c28 --- /dev/null +++ b/tests/Bernard/Tests/BatchTest.php @@ -0,0 +1,68 @@ +assertInternalType('string', $batch->getName()); + } + + public function testStatus() + { + $batch = new Batch(null, null, new Status(10, 5, 3)); + + $this->assertEquals(new Status(10, 5, 3), $batch->getStatus()); + } + + public function testEnvelopeIsCreatedWithBatchStamp() + { + $batch = new Batch('my-id'); + $batch->assign($this->getMock('Bernard\Message')); + + $envelopes = $batch->flush(); + + $this->assertEquals('my-id', $envelopes[0]->getStamp('batch')); + } + + public function testReuseKey() + { + $batch = new Batch('my-key'); + + $this->assertEquals('my-key', $batch->getName()); + } + + public function testAssigningMessageUpdatesTotal() + { + $message = $this->getMock('Bernard\Message'); + + $batch = new Batch('my-id'); + $batch->assign($message); + + $this->assertEquals(new Status(1, 0, 0), $batch->getStatus()); + } + + public function testFlushResetArray() + { + $message = $this->getMock('Bernard\Message'); + + $batch = new Batch; + $batch->assign($message); + + $this->assertEquals(new Status(1, 0, 0), $batch->getStatus()); + + $envelopes = $batch->flush(); + + $this->assertContainsOnlyInstancesOf('Bernard\Envelope', $envelopes); + $this->assertCount(1, $envelopes); + + $this->assertCount(0, $batch->flush()); + } +} diff --git a/tests/Bernard/Tests/EnvelopeTest.php b/tests/Bernard/Tests/EnvelopeTest.php index 66db3715..59a2fc97 100644 --- a/tests/Bernard/Tests/EnvelopeTest.php +++ b/tests/Bernard/Tests/EnvelopeTest.php @@ -16,4 +16,30 @@ public function testItWrapsAMessageWithMetadata() $this->assertEquals('SendNewsletter', $envelope->getName()); $this->assertSame($message, $envelope->getMessage()); } + + public function testItSupportsStamps() + { + $envelope = new Envelope(new DefaultMessage('SendNewsletter', array()), array( + 'stamp_01' => 'this is the value for "stamp_01"', + 'stamp_02' => 'this is the value for "stamp_02"', + 'stamp_03' => 8151, + )); + + $this->assertEquals('this is the value for "stamp_01"', $envelope->getStamp('stamp_01')); + $this->assertEquals('this is the value for "stamp_02"', $envelope->getStamp('stamp_02')); + $this->assertEquals(8151, $envelope->getStamp('stamp_03')); + $this->assertEquals('default', $envelope->getStamp('undefined_stamp', 'default')); + $this->assertNull($envelope->getStamp('undefined_stamp')); + } + + public function testItStampsCanOnlyBeScalarTypes() + { + $envelope = new Envelope(new DefaultMessage('SendNewsletter', array()), array( + 'stamp_01' => array('i', 'am', 'very', 'complex'), + 'stamp_02' => new DefaultMessage('SendNewsletter', array()), + )); + + $this->assertNull($envelope->getStamp('stamp_01')); + $this->assertNull($envelope->getStamp('stamp_02')); + } } diff --git a/tests/Bernard/Tests/EventListener/BatchSubscriberTest.php b/tests/Bernard/Tests/EventListener/BatchSubscriberTest.php new file mode 100644 index 00000000..50dd88c9 --- /dev/null +++ b/tests/Bernard/Tests/EventListener/BatchSubscriberTest.php @@ -0,0 +1,64 @@ +storage = $this->getMock('Bernard\Batch\Storage'); + + $this->dispatcher = new EventDispatcher; + $this->dispatcher->addSubscriber(new BatchSubscriber($this->storage)); + } + + public function testItRegistersOnProduce() + { + $this->storage->expects($this->once())->method('register') + ->with('my-batch-name'); + + $envelope = $this->getMockBuilder('Bernard\Envelope') + ->disableOriginalConstructor()->getMock(); + $envelope->expects($this->any())->method('getStamp')->with('batch') + ->will($this->returnValue('my-batch-name')); + + $event = new EnvelopeEvent($envelope, $this->getMock('Bernard\Queue')); + + $this->dispatcher->dispatch('bernard.produce', $event); + } + + public function testItIncrementsOnReject() + { + $this->storage->expects($this->once())->method('increment') + ->with('my-batch-name', 'failed'); + + $envelope = $this->getMockBuilder('Bernard\Envelope') + ->disableOriginalConstructor()->getMock(); + $envelope->expects($this->any())->method('getStamp')->with('batch') + ->will($this->returnValue('my-batch-name')); + + $event = new RejectEnvelopeEvent($envelope, $this->getMock('Bernard\Queue'), new \Exception); + + $this->dispatcher->dispatch('bernard.reject', $event); + } + + public function testItIncrementsOnAcknowledge() + { + $this->storage->expects($this->once())->method('increment') + ->with('my-batch-name', 'successful'); + + $envelope = $this->getMockBuilder('Bernard\Envelope') + ->disableOriginalConstructor()->getMock(); + $envelope->expects($this->any())->method('getStamp')->with('batch') + ->will($this->returnValue('my-batch-name')); + + $event = new EnvelopeEvent($envelope, $this->getMock('Bernard\Queue')); + + $this->dispatcher->dispatch('bernard.acknowledge', $event); + } +} diff --git a/tests/Bernard/Tests/EventListener/FailureSubscriberTest.php b/tests/Bernard/Tests/EventListener/FailureSubscriberTest.php index 0dfb2804..9b6083e1 100644 --- a/tests/Bernard/Tests/EventListener/FailureSubscriberTest.php +++ b/tests/Bernard/Tests/EventListener/FailureSubscriberTest.php @@ -5,13 +5,16 @@ use Bernard\Event\RejectEnvelopeEvent; use Bernard\EventListener\FailureSubscriber; use Bernard\QueueFactory\InMemoryFactory; +use Symfony\Component\EventDispatcher\EventDispatcher; class FailureSubscriberTest extends \PHPUnit_Framework_TestCase { public function setUp() { $this->queues = new InMemoryFactory; - $this->subscriber = new FailureSubscriber($this->queues); + + $this->dispatcher = new EventDispatcher; + $this->dispatcher->addSubscriber(new FailureSubscriber($this->queues)); } public function testAcknowledgeMessageAndEnqueue() @@ -22,7 +25,7 @@ public function testAcknowledgeMessageAndEnqueue() $queue = $this->getMock('Bernard\Queue'); $queue->expects($this->once())->method('acknowledge')->with($envelope); - $this->subscriber->onReject(new RejectEnvelopeEvent($envelope, $queue, new \Exception)); + $this->dispatcher->dispatch('bernard.reject', new RejectEnvelopeEvent($envelope, $queue, new \Exception())); $this->assertCount(1, $this->queues->create('failed')); $this->assertSame($envelope, $this->queues->create('failed')->dequeue()); diff --git a/tests/Bernard/Tests/ProducerTest.php b/tests/Bernard/Tests/ProducerTest.php index 619e8b39..db61be89 100644 --- a/tests/Bernard/Tests/ProducerTest.php +++ b/tests/Bernard/Tests/ProducerTest.php @@ -6,6 +6,7 @@ use Bernard\Message\DefaultMessage; use Bernard\QueueFactory\InMemoryFactory; use Symfony\Component\EventDispatcher\EventDispatcher; +use Bernard\Batch; class ProducerTest extends \PHPUnit_Framework_TestCase { @@ -43,6 +44,36 @@ public function testItDelegatesMessagesToQueue() $this->assertSame($message, $envelope->getMessage()); } + public function testItSupportsBatches() + { + $message1 = new DefaultMessage('SendNewsletter'); + $message2 = new DefaultMessage('SomeThingElse'); + + $batch = new Batch('my-id'); + $batch->assign($message1); + $batch->assign($message2); + + $this->producer->produce($batch); + + $this->assertCount(1, $this->queues->create('send-newsletter')); + $this->assertCount(1, $this->queues->create('some-thing-else')); + } + + public function testItBatchesToForcedQueue() + { + $message1 = new DefaultMessage('SendNewsletter'); + $message2 = new DefaultMessage('SomeThingElse'); + + $batch = new Batch('my-id'); + $batch->assign($message1); + $batch->assign($message2); + + $this->producer->produce($batch, 'high'); + + $this->assertCount(2, $this->queues->create('high')); + $this->assertCount(0, $this->queues->create('send-newsletter')); + } + public function testItUsesGivenQueueName() { $message = new DefaultMessage('SendNewsletter'); diff --git a/tests/Bernard/Tests/Serializer/AbstractSerializerTest.php b/tests/Bernard/Tests/Serializer/AbstractSerializerTest.php index 6ad7edeb..00e38e15 100644 --- a/tests/Bernard/Tests/Serializer/AbstractSerializerTest.php +++ b/tests/Bernard/Tests/Serializer/AbstractSerializerTest.php @@ -69,8 +69,37 @@ public function testItDeserializesDefaultMessage() $this->assertEquals($message, $this->serializer->deserialize($json)); } - public function createWrappedDefaultMessage($name, array $properties = array()) + public function testItDeserializesDefaultMessageWithStamps() { - return new Envelope(new DefaultMessage($name, $properties)); + $message = $this->createWrappedDefaultMessage('SendNewsletter', array(), array( + 'stamp_01' => 'this is the value for "stamp_01"', + 'stamp_02' => 'this is the value for "stamp_02"', + 'stamp_03' => 8151, + )); + + $json = $this->serializer->serialize($message); + + $this->assertEquals($message, $this->serializer->deserialize($json)); + } + + public function testItDeserializesStampsWithoutOvervideOfEnvelopeParameters() + { + $envelope = $this->createWrappedDefaultMessage('SendNewsletter', array(), array( + 'timestamp' => 'timestamp is not allow', + 'class' => 'class is not allowed', + 'args' => 'args are not allowed', + )); + + $json = $this->serializer->serialize($envelope); + $envelope = $this->serializer->deserialize($json); + + $this->assertNull($envelope->getStamp('timestamp')); + $this->assertNull($envelope->getStamp('class')); + $this->assertNull($envelope->getStamp('args')); + } + + public function createWrappedDefaultMessage($name, array $properties = array(), array $stamps = array()) + { + return new Envelope(new DefaultMessage($name, $properties), $stamps); } } diff --git a/tests/Bernard/Tests/Serializer/SimpleSerializerTest.php b/tests/Bernard/Tests/Serializer/SimpleSerializerTest.php index 67abf5d4..5145ae07 100644 --- a/tests/Bernard/Tests/Serializer/SimpleSerializerTest.php +++ b/tests/Bernard/Tests/Serializer/SimpleSerializerTest.php @@ -69,4 +69,18 @@ public function testItDeserializesDefaultMessage() $this->assertEquals($envelope, $this->serializer->deserialize($json)); } + + + public function testItDeserializesDefaultMessageWithStamps() + { + $envelope = new Envelope(new DefaultMessage('SendNewsletter', array()), array( + 'stamp_01' => 'this is the value for "stamp_01"', + 'stamp_02' => 'this is the value for "stamp_02"', + 'stamp_03' => 8151, + )); + $json = $this->serializer->serialize($envelope); + + $this->assertEquals($envelope, $this->serializer->deserialize($json)); + } + }