/**
   * Test of asynchronouslySendNotificationMessage method, of class PushManager.
   *
   * @throws Exception If an error occurs
   */
  public void testAsynchronouslySendNotificationMessage_SendMoreThanOneMessage() throws Exception {

    final int messagesToSend = 100;
    final int sendingTimeSeconds = 2;

    final MockHelperNotificationEngine mockNotificationEngine =
        new MockHelperNotificationEngine() {
          @Override
          public void sendNotificationMessage(
              String username, String deviceId, Alert[] alerts, int uimode)
              throws NotificationNotSentException, NotificationException {
            idleFor(sendingTimeSeconds);
            incrementMessagesSent();
          }

          public void validate() {
            assertEquals("All messages have to be sent", messagesToSend, totalMessageSent);
          }
        };

    PushManager instance =
        new PushManager() {
          @Override
          protected NotificationEngine createNotificationEngine() {
            return mockNotificationEngine;
          }
        };

    Future<?>[] futures = new Future<?>[messagesToSend];
    for (int i = 0; i < messagesToSend; ++i) {
      String username = "******";
      String deviceId = "IMEI-1234567890";
      Alert[] alerts = new Alert[] {new Alert()};
      int uimode = 0;
      futures[i] =
          instance.asynchronouslySendNotificationMessage(username, deviceId, alerts, uimode);
    }

    Thread.sleep(100);

    // the notification messages deliveries are just started so they are all in progress
    assertEquals(
        Math.min(instance.getCoreThreadPoolSize(), messagesToSend),
        instance.getCurrentPushInProgressCount());
    assertEquals(
        Math.max(0, messagesToSend - instance.getCoreThreadPoolSize()),
        instance.getQueuedPushCount());

    waitingDeliveryTermination(futures, sendingTimeSeconds);
    assertEquals(0, instance.getCurrentPushInProgressCount());

    mockNotificationEngine.validate();
  }
  /**
   * Test of asynchronouslySendNotificationMessage method, of class PushManager. The allowed threads
   * and the queue capacity is reached before the first request is fulfilled. The exceeding requests
   * are rejected by the MyRejectedExecutionHandler
   *
   * @throws Exception If an error occurs
   */
  public void testAsynchronouslySendNotificationMessages_SmalQueue_SendMoreThanOneMessage()
      throws Exception {

    final int messagesToSend = 100;
    final int sendingTimeSeconds = 2;

    final int queueCapacity = 7;
    final int corePoolSize = 1;
    final int maximumPoolSize = 20;

    final MockHelperNotificationEngine mockNotificationEngine =
        new MockHelperNotificationEngine() {
          @Override
          public void sendNotificationMessages(String username, Alert[] alerts, int uimode)
              throws NotificationNotSentException, NotificationException {
            idleFor(sendingTimeSeconds);
            incrementMessagesSent();
          }
          // the messages actually sent are equal to the sum of the
          // maximumPoolSize and the queueCapacity. All other messages
          // are discarded
          public void validate() {
            assertEquals(maximumPoolSize + queueCapacity, totalMessageSent);
          }
        };

    PushManager instance =
        new PushManager() {
          @Override
          protected NotificationEngine createNotificationEngine() {
            return mockNotificationEngine;
          }
        };

    instance.setCoreThreadPoolSize(corePoolSize);
    instance.setMaximumThreadPoolSize(maximumPoolSize);
    instance.setQueueCapacity(queueCapacity);
    instance.init();

    int rejectedMessages = 0;

    Future<?>[] futures = new Future<?>[messagesToSend];
    for (int i = 0; i < messagesToSend; ++i) {
      try {
        String username = "******";
        Alert[] alerts = new Alert[] {new Alert()};
        int uimode = 0;
        futures[i] = instance.asynchronouslySendNotificationMessages(username, alerts, uimode);
      } catch (RejectedExecutionException ex) {
        futures[i] = null;
        ++rejectedMessages;
      }
    }

    waitingDeliveryTermination(futures, sendingTimeSeconds);

    assertEquals(0, instance.getCurrentPushInProgressCount());
    mockNotificationEngine.validate();
    assertEquals(messagesToSend - maximumPoolSize - queueCapacity, rejectedMessages);
  }
  public void testAsynchronouslySendNotificationMessage_SmalQueue_SendLessThanTheCorePoolSize()
      throws Exception {

    // All messages are sent befor the first is fulfilled
    final int sendingTimeSeconds = 2;

    // the number of messages to send is greater than the corePoolSize but
    // less than the corePoolSize plus the queueCapacity so no new threads
    // are added
    final int messagesToSend = 8;

    final int queueCapacity = 10;
    final int corePoolSize = 10;
    final int maximumPoolSize = 30;

    final MockHelperNotificationEngine mockNotificationEngine =
        new MockHelperNotificationEngine() {
          @Override
          public void sendNotificationMessage(
              String username, String deviceId, Alert[] alerts, int uimode)
              throws NotificationNotSentException, NotificationException {
            idleFor(sendingTimeSeconds);
            incrementMessagesSent();
          }
          // the messages actually sent are equal to the sum of the
          // maximumPoolSize and the queueCapacity. All other messages
          // are discarded
          public void validate() {
            assertEquals(
                Math.min(messagesToSend, maximumPoolSize + queueCapacity), totalMessageSent);
          }
        };

    PushManager instance =
        new PushManager() {
          @Override
          protected NotificationEngine createNotificationEngine() {
            return mockNotificationEngine;
          }
        };

    instance.setCoreThreadPoolSize(corePoolSize);
    instance.setMaximumThreadPoolSize(maximumPoolSize);
    instance.setQueueCapacity(queueCapacity);
    instance.init();

    int rejectedMessages = 0;

    Future<?>[] futures = new Future<?>[messagesToSend];
    for (int i = 0; i < messagesToSend; ++i) {
      try {
        String username = "******";
        String deviceId = "IMEI-1234567890";
        Alert[] alerts = new Alert[] {new Alert()};
        int uimode = 0;
        futures[i] =
            instance.asynchronouslySendNotificationMessage(username, deviceId, alerts, uimode);
      } catch (RejectedExecutionException ex) {
        futures[i] = null;
        ++rejectedMessages;
      }
    }

    waitingDeliveryTermination(futures, sendingTimeSeconds);
    assertEquals(0, instance.getCurrentPushInProgressCount());

    mockNotificationEngine.validate();
    assertEquals(Math.max(0, messagesToSend - maximumPoolSize - queueCapacity), rejectedMessages);
    // every new message to send increase the number of threads until the
    // corePoolSize is reached.
    // every message exceeding the corePoolSize is enqueued until the
    // queueCapacity is reached.
    //
    int numThreads =
        Math.max(
            Math.min(corePoolSize, messagesToSend),
            Math.min(maximumPoolSize, messagesToSend - queueCapacity));
    assertEquals(numThreads, instance.getThreadPoolSize());
    assertEquals(messagesToSend, numThreads);
  }