<?php

require_once 'Swift/Tests/SwiftUnitTestCase.php';
require_once 'Swift/Plugins/ThrottlerPlugin.php';
require_once 'Swift/Events/SendEvent.php';
require_once 'Swift/Plugins/Sleeper.php';
require_once 'Swift/Plugins/Timer.php';
require_once 'Swift/Mime/Message.php';

class Swift_Plugins_ThrottlerPluginTest extends Swift_Tests_SwiftUnitTestCase
{
  
  public function testBytesPerMinuteThrottling()
  {
    $sleeper = $this->_createSleeper();
    $timer = $this->_createTimer();
    
    //10MB/min
    $plugin = new Swift_Plugins_ThrottlerPlugin(
      10000000, Swift_Plugins_ThrottlerPlugin::BYTES_PER_MINUTE,
      $sleeper, $timer
      );
    
    $this->_checking(Expectations::create()
      -> one($timer)->getTimestamp() -> returns(0)
      -> one($timer)->getTimestamp() -> returns(1) //expected 0.6
      -> one($timer)->getTimestamp() -> returns(1) //expected 1.2 (sleep 1)
      -> one($timer)->getTimestamp() -> returns(2) //expected 1.8
      -> one($timer)->getTimestamp() -> returns(2) //expected 2.4 (sleep 1)
      -> ignoring($timer)
      
      -> exactly(2)->of($sleeper)->sleep(1)
      );
    
    //10,000,000 bytes per minute
    //100,000 bytes per email
    
    // .: (10,000,000/100,000)/60 emails per second = 1.667 emais/sec
    
    $message = $this->_createMessageWithByteCount(100000); //100KB
    
    $evt = $this->_createSendEvent($message);
    
    for ($i = 0; $i < 5; ++$i)
    {
      $plugin->beforeSendPerformed($evt);
      $plugin->sendPerformed($evt);
    }
  }
  
  public function testMessagesPerMinuteThrottling()
  {
    $sleeper = $this->_createSleeper();
    $timer = $this->_createTimer();
    
    //60/min
    $plugin = new Swift_Plugins_ThrottlerPlugin(
      60, Swift_Plugins_ThrottlerPlugin::MESSAGES_PER_MINUTE,
      $sleeper, $timer
      );
    
    $this->_checking(Expectations::create()
      -> one($timer)->getTimestamp() -> returns(0)
      -> one($timer)->getTimestamp() -> returns(0) //expected 1 (sleep 1)
      -> one($timer)->getTimestamp() -> returns(2) //expected 2
      -> one($timer)->getTimestamp() -> returns(2) //expected 3 (sleep 1)
      -> one($timer)->getTimestamp() -> returns(4) //expected 4
      -> ignoring($timer)
      
      -> exactly(2)->of($sleeper)->sleep(1)
      );
      
    //60 messages per minute
    //1 message per second
    
    $message = $this->_createMessageWithByteCount(10);
    
    $evt = $this->_createSendEvent($message);
    
    for ($i = 0; $i < 5; ++$i)
    {
      $plugin->beforeSendPerformed($evt);
      $plugin->sendPerformed($evt);
    }
  }
  
  // -- Creation Methods
  
  private function _createSleeper()
  {
    return $this->_mock('Swift_Plugins_Sleeper');
  }
  
  private function _createTimer()
  {
    return $this->_mock('Swift_Plugins_Timer');
  }
  
  private function _createMessageWithByteCount($bytes)
  {
    $this->_bytes = $bytes;
    $msg = $this->_mock('Swift_Mime_Message');
    $this->_checking(Expectations::create()
      -> ignoring($msg)->toByteStream(any()) -> calls(array($this, '_write'))
    );
    return $msg;
  }
  
  private function _createSendEvent($message)
  {
    $evt = $this->_mock('Swift_Events_SendEvent');
    $this->_checking(Expectations::create()
      -> ignoring($evt)->getMessage() -> returns($message)
      );
    return $evt;
  }
  
  private $_bytes = 0;
  public function _write($invocation)
  {
    $args = $invocation->getArguments();
    $is = $args[0];
    for ($i = 0; $i < $this->_bytes; ++$i)
    {
      $is->write('x');
    }
  }
  
}