Package org.sonar.server.notifications

Source Code of org.sonar.server.notifications.NotificationServiceTest

/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package org.sonar.server.notifications;

import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.config.Settings;
import org.sonar.api.notifications.Notification;
import org.sonar.api.notifications.NotificationChannel;
import org.sonar.api.notifications.NotificationDispatcher;
import org.sonar.core.notification.DefaultNotificationManager;
import org.sonar.jpa.session.DatabaseSessionFactory;

import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class NotificationServiceTest {
  private static String CREATOR_SIMON = "simon";
  private static String CREATOR_EVGENY = "evgeny";
  private static String ASSIGNEE_SIMON = "simon";

  private final DefaultNotificationManager manager = mock(DefaultNotificationManager.class);
  private final Notification notification = mock(Notification.class);
  private final NotificationChannel emailChannel = mock(NotificationChannel.class);
  private final NotificationChannel gtalkChannel = mock(NotificationChannel.class);
  private final NotificationDispatcher commentOnReviewAssignedToMe = mock(NotificationDispatcher.class);
  private final NotificationDispatcher commentOnReviewCreatedByMe = mock(NotificationDispatcher.class);

  private NotificationService service;

  private void setUpMocks(String creator, String assignee) {
    when(emailChannel.getKey()).thenReturn("email");
    when(gtalkChannel.getKey()).thenReturn("gtalk");
    when(commentOnReviewAssignedToMe.getKey()).thenReturn("comment on review assigned to me");
    when(commentOnReviewCreatedByMe.getKey()).thenReturn("comment on review created by me");
    when(manager.getFromQueue()).thenReturn(notification).thenReturn(null);

    Settings settings = new Settings().setProperty("sonar.notifications.delay", 1L);

    service = new NotificationService(settings, manager, mock(DatabaseSessionFactory.class),
      new NotificationDispatcher[] {commentOnReviewAssignedToMe, commentOnReviewCreatedByMe});
  }

  /**
   * Given:
   * Simon wants to receive notifications by email on comments for reviews assigned to him or created by him.
   *
   * When:
   * Freddy adds comment to review created by Simon and assigned to Simon.
   *
   * Then:
   * Only one notification should be delivered to Simon by Email.
   */
  @Test
  public void scenario1() {
    setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON);
    doAnswer(addUser(ASSIGNEE_SIMON, emailChannel)).when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
    doAnswer(addUser(CREATOR_SIMON, emailChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));

    service.start();
    verify(emailChannel, timeout(2000)).deliver(notification, ASSIGNEE_SIMON);
    service.stop();

    verify(gtalkChannel, never()).deliver(notification, ASSIGNEE_SIMON);
  }

  /**
   * Given:
   * Evgeny wants to receive notification by GTalk on comments for reviews created by him.
   * Simon wants to receive notification by Email on comments for reviews assigned to him.
   *
   * When:
   * Freddy adds comment to review created by Evgeny and assigned to Simon.
   *
   * Then:
   * Two notifications should be delivered - one to Simon by Email and another to Evgeny by GTalk.
   */
  @Test
  public void scenario2() {
    setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
    doAnswer(addUser(ASSIGNEE_SIMON, emailChannel)).when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
    doAnswer(addUser(CREATOR_EVGENY, gtalkChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));

    service.start();
    verify(emailChannel, timeout(2000)).deliver(notification, ASSIGNEE_SIMON);
    verify(gtalkChannel, timeout(2000)).deliver(notification, CREATOR_EVGENY);
    service.stop();

    verify(emailChannel, never()).deliver(notification, CREATOR_EVGENY);
    verify(gtalkChannel, never()).deliver(notification, ASSIGNEE_SIMON);
  }

  /**
   * Given:
   * Simon wants to receive notifications by Email and GTLak on comments for reviews assigned to him.
   *
   * When:
   * Freddy adds comment to review created by Evgeny and assigned to Simon.
   *
   * Then:
   * Two notifications should be delivered to Simon - one by Email and another by GTalk.
   */
  @Test
  public void scenario3() {
    setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
    doAnswer(addUser(ASSIGNEE_SIMON, new NotificationChannel[] {emailChannel, gtalkChannel}))
      .when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));

    service.start();
    verify(emailChannel, timeout(2000)).deliver(notification, ASSIGNEE_SIMON);
    verify(gtalkChannel, timeout(2000)).deliver(notification, ASSIGNEE_SIMON);
    service.stop();

    verify(emailChannel, never()).deliver(notification, CREATOR_EVGENY);
    verify(gtalkChannel, never()).deliver(notification, CREATOR_EVGENY);
  }

  /**
   * Given:
   * Nobody wants to receive notifications.
   *
   * When:
   * Freddy adds comment to review created by Evgeny and assigned to Simon.
   *
   * Then:
   * No notifications.
   */
  @Test
  public void scenario4() {
    setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);

    service.start();
    service.stop();

    verify(emailChannel, never()).deliver(any(Notification.class), anyString());
    verify(gtalkChannel, never()).deliver(any(Notification.class), anyString());
  }

  // SONAR-4548
  @Test
  public void shouldNotStopWhenException() {
    setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON);
    when(manager.getFromQueue()).thenThrow(new RuntimeException("Unexpected exception")).thenReturn(notification).thenReturn(null);
    doAnswer(addUser(ASSIGNEE_SIMON, emailChannel)).when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
    doAnswer(addUser(CREATOR_SIMON, emailChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));

    service.start();
    verify(emailChannel, timeout(2000)).deliver(notification, ASSIGNEE_SIMON);
    service.stop();

    verify(gtalkChannel, never()).deliver(notification, ASSIGNEE_SIMON);
  }

  @Test
  public void shouldNotAddNullAsUser() {
    setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
    doAnswer(addUser(null, gtalkChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));

    service.start();
    service.stop();

    verify(emailChannel, never()).deliver(any(Notification.class), anyString());
    verify(gtalkChannel, never()).deliver(any(Notification.class), anyString());
  }

  @Test
  public void shouldReturnDispatcherList() {
    setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON);

    assertThat(service.getDispatchers()).containsOnly(commentOnReviewAssignedToMe, commentOnReviewCreatedByMe);
  }

  @Test
  public void shouldReturnNoDispatcher() {
    Settings settings = new Settings().setProperty("sonar.notifications.delay", 1L);

    service = new NotificationService(settings, manager, mock(DatabaseSessionFactory.class));
    assertThat(service.getDispatchers()).hasSize(0);
  }

  @Test
  public void shouldLogEvery10Minutes() throws InterruptedException {
    setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
    // Emulate 2 notifications in DB
    when(manager.getFromQueue()).thenReturn(notification).thenReturn(notification).thenReturn(null);
    when(manager.count()).thenReturn(1L).thenReturn(0L);
    service = spy(service);
    // Emulate processing of each notification take 10 min to have a log each time
    when(service.now()).thenReturn(0L).thenReturn(10 * 60 * 1000 + 1L).thenReturn(20 * 60 * 1000 + 2L);
    service.start();
    verify(service, timeout(200)).log(1, 1, 10);
    verify(service, timeout(200)).log(2, 0, 20);
    service.stop();
  }

  private static Answer<Object> addUser(final String user, final NotificationChannel channel) {
    return addUser(user, new NotificationChannel[] {channel});
  }

  private static Answer<Object> addUser(final String user, final NotificationChannel[] channels) {
    return new Answer<Object>() {
      public Object answer(InvocationOnMock invocation) {
        for (NotificationChannel channel : channels) {
          ((NotificationDispatcher.Context) invocation.getArguments()[1]).addUser(user, channel);
        }
        return null;
      }
    };
  }
}
TOP

Related Classes of org.sonar.server.notifications.NotificationServiceTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.