Package org.waveprotocol.wave.model.supplement

Source Code of org.waveprotocol.wave.model.supplement.SupplementedWaveImplTest

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.wave.model.supplement;

import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import junit.framework.TestCase;

import org.waveprotocol.wave.model.conversation.Blips;
import org.waveprotocol.wave.model.conversation.ConversationBlip;
import org.waveprotocol.wave.model.conversation.ObservableConversationThread;
import org.waveprotocol.wave.model.conversation.WaveletBasedConversation;
import org.waveprotocol.wave.model.conversation.testing.FakeConversationView;
import org.waveprotocol.wave.model.id.IdGenerator;
import org.waveprotocol.wave.model.id.IdUtil;
import org.waveprotocol.wave.model.id.WaveletId;
import org.waveprotocol.wave.model.schema.SchemaCollection;
import org.waveprotocol.wave.model.schema.account.AccountSchemas;
import org.waveprotocol.wave.model.schema.conversation.ConversationSchemas;
import org.waveprotocol.wave.model.schema.supplement.UserDataSchemas;
import org.waveprotocol.wave.model.supplement.SupplementedWaveImpl.DefaultFollow;
import org.waveprotocol.wave.model.testing.FakeIdGenerator;
import org.waveprotocol.wave.model.util.CollectionUtils;
import org.waveprotocol.wave.model.version.HashedVersion;
import org.waveprotocol.wave.model.wave.ParticipantId;
import org.waveprotocol.wave.model.wave.Wavelet;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

/**
* Tests for {@link SupplementedWaveImpl}.
*
*/

public final class SupplementedWaveImplTest extends TestCase {

  /**
   * Stub for a wave view, exposing versioned wavelets, and allowing version
   * increments.
   */
  private static class StubSupplementWaveView implements SupplementWaveView {
    private final Map<WaveletId, Long> versions = CollectionUtils.newHashMap();
    private final Map<WaveletId, Map<String, Long>> blipVersions = CollectionUtils.newHashMap();
    private boolean isExplicitParticipant;

    @Override
    public long getVersion(WaveletId id) {
      return versions.get(id);
    }

    @Override
    public HashedVersion getSignature(WaveletId id) {
      return HashedVersion.unsigned(0);
    }

    @Override
    public Iterable<WaveletId> getWavelets() {
      return versions.keySet();
    }

    @Override
    public Map<String, Long> getBlipVersions(WaveletId id) {
      return blipVersions.get(id);
    }

    @Override
    public boolean isExplicitParticipant() {
      return isExplicitParticipant;
    }

    public void put(WaveletId id, long version) {
      versions.put(id, version);
    }

    public void putBlipVersion(WaveletId id, String blipId, long version) {
      Map<String, Long> waveletBlipVersions = blipVersions.get(id);
      if (waveletBlipVersions == null) {
        waveletBlipVersions = CollectionUtils.newHashMap();
        blipVersions.put(id, waveletBlipVersions);
      }
      waveletBlipVersions.put(blipId, version);
    }

    /** Increments the version of a wavelet. */
    public void touch(WaveletId id) {
      if (versions.containsKey(id)) {
        versions.put(id, versions.get(id) + 1);
      }
    }
  }

  private static final SchemaCollection schemas = new SchemaCollection();
  static {
    schemas.add(new AccountSchemas());
    schemas.add(new ConversationSchemas());
    schemas.add(new UserDataSchemas());
  }

  private static final WaveletId ROOT;
  private static final String ROOT_BLIP1;

  private static final WaveletId W1;
  private static final String W1_BLIP1;
  private static final long ROOT_VERSION = 30;
  private static final long ROOT_BLIP1_VERSION = 28;

  private static final long W1_VERSION = 20;
  private static final long W1_BLIP1_VERSION = 15;

  private final static Map<WaveletId, Long> EXPECTED_ARCHIVE_VERSIONS;

  static {
    IdGenerator generator = FakeIdGenerator.create();
    ROOT = generator.newConversationRootWaveletId();
    W1 = generator.newConversationWaveletId();
    ROOT_BLIP1 = generator.newBlipId();
    W1_BLIP1 = generator.newBlipId();
    EXPECTED_ARCHIVE_VERSIONS = CollectionUtils.newHashMap();
    EXPECTED_ARCHIVE_VERSIONS.put(ROOT, ROOT_VERSION);
    EXPECTED_ARCHIVE_VERSIONS.put(W1, W1_VERSION);
  }

  private StubSupplementWaveView wave;
  private PrimitiveSupplement substrate;
  private SupplementedWave supplement;

  @Override
  protected void setUp() throws Exception {
    //
    // Initial state is:
    //  * a wave with two wavelets in view, ROOT and W1, at particular versions.
    //  * an empty supplement.
    //

    substrate = new PrimitiveSupplementImpl();
    wave = new StubSupplementWaveView();

    wave.put(ROOT, ROOT_VERSION);
    wave.put(W1, W1_VERSION);
    wave.putBlipVersion(ROOT, ROOT_BLIP1, ROOT_BLIP1_VERSION);
    wave.putBlipVersion(W1, W1_BLIP1, W1_BLIP1_VERSION);

    supplement = SupplementedWaveImpl.create(substrate, wave, DefaultFollow.ALWAYS);
  }

  private void createEmptyWave() {
    substrate = new PrimitiveSupplementImpl();
    wave = new StubSupplementWaveView();
    supplement = SupplementedWaveImpl.create(substrate, wave, DefaultFollow.ALWAYS);
  }

  /**
   * Sets up the test supplement with a real wave model behind it.
   */
  private WaveletBasedConversation setUpWithWaveModel() {
    FakeConversationView view = FakeConversationView.builder().with(schemas).build();
    WaveletBasedConversation conversation = view.createRoot();
    ParticipantId viewer = new ParticipantId("nobody@nowhere.com");
    supplement = SupplementedWaveImpl.create(substrate, view, viewer, DefaultFollow.ALWAYS);
    return conversation;
  }

  private void addTags(Wavelet wavelet) {
    wavelet.getDocument(IdUtil.TAGS_DOC_ID);
  }

  //
  // Environment tests.
  //

  public void testIncorrectExternalWaveViewThrowsException() {
    // Make view return a non-conversational id, and test that supplement actions throw exceptions.
    wave.put(FakeIdGenerator.create().newUserDataWaveletId("foo@bar.com"), 20);

    try {
      supplement.archive();
      fail();
    } catch (RuntimeException e) {
      // expected
    }

    try {
      supplement.markAsRead();
      fail();
    } catch (RuntimeException e) {
      // expected
    }
  }

  //
  // Read/unread tests.
  //

  public void testNewBlipIsUnread() {
    WaveletBasedConversation c = setUpWithWaveModel();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    assertTrue(supplement.isUnread(b));
  }

  public void testMarkBlipAsReadAffectsBlipReadState() {
    WaveletBasedConversation c = setUpWithWaveModel();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    supplement.markAsRead(b);
    assertFalse(supplement.isUnread(b));
  }

  public void testMarkBlipIsIdempotent() {
    // Use real wave-model view.
    WaveletBasedConversation c = setUpWithWaveModel();
    Wavelet w = c.getWavelet();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    supplement.markAsRead(b);
    int blipReadVersion = substrate.getLastReadBlipVersion(w.getId(), b.getId());
    int waveletVersion = (int) w.getVersion();
    assertEquals(waveletVersion, blipReadVersion);

    // Do something to increase wavelet version without increasing blip last-modified version.
    t.appendBlip();
    assert w.getVersion() > waveletVersion : "test wave model did not increase version";

    // Test that marking blip as read again has no effect.
    supplement.markAsRead(b);
    long newBlipReadVersion = substrate.getLastReadBlipVersion(w.getId(), b.getId());
    assertEquals(blipReadVersion, (int) newBlipReadVersion);
  }

  public void testMarkingBlipAsReadAfterWaveUnreadMarksAtWaveletVersion() {
    // Mark blip as read, then mark wavelet as unread, then mark blip as read
    // again, and test that it is marked at wavelet version. There is no real
    // design reason to test this use case; this is just here because it was a
    // specific case that was failing before.
    WaveletBasedConversation c = setUpWithWaveModel();
    Wavelet w = c.getWavelet();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    supplement.markAsRead(b);
    supplement.markAsUnread();

    // Do something to increase wavelet version without increasing blip last-modified version.
    t.appendBlip();

    // Mark as read again, test that it's marked at wavelet version.
    supplement.markAsRead(b);
    int blipReadVersion = substrate.getLastReadBlipVersion(w.getId(), b.getId());
    assertEquals(blipReadVersion, (int) w.getVersion());
  }

  public void testMarkingBlipAsReadAfterBlipModifiedMarksAtWaveletVersion() {
    // Mark blip as read, then mark wavelet as unread, then mark blip as read
    // again, and test that it is marked at wavelet version. There is no real
    // design reason to test this use case; this is just here because it was a
    // specific case that was failing before.
    WaveletBasedConversation c = setUpWithWaveModel();
    Wavelet w = c.getWavelet();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    supplement.markAsRead(b);
    supplement.markAsUnread();

    // Increase both last-modified blip version and wavelet version (but latter more than former).
    b.getContent().appendXml(Blips.INITIAL_CONTENT);
    t.appendBlip();

    // Mark as read again, test that it's marked at wavelet version, not blip last-modified version.
    supplement.markAsRead(b);
    long blipReadVersion = substrate.getLastReadBlipVersion(w.getId(), b.getId());
    assertEquals(blipReadVersion, (int) w.getVersion());
  }

  //
  // Wave state tests (inbox / archive / mute).
  //

  private void assertIsInbox() {
    assertTrue(supplement.isInbox());
    assertFalse(supplement.isArchived());
    assertFalse(supplement.isMute());
  }

  private void assertIsArchived() {
    assertFalse(supplement.isInbox());
    assertTrue(supplement.isArchived());
    assertFalse(supplement.isMute());
  }

  private void assertIsUnfollowed() {
    assertFalse(supplement.isInbox());
    assertFalse(supplement.isArchived());
    assertTrue(supplement.isMute());
  }

  public void testUnmutedUnarchivedIsInbox() {
    assertIsInbox();
  }

  public void testEmptyWaveState() {
    createEmptyWave();
    assertIsArchived();
  }

  public void testUnmutedSomeArchivedIsInbox() {
    substrate.archiveAtVersion(ROOT, (int) ROOT_VERSION);
    assertIsInbox();
  }

  public void testUnmutedArchivedIsNotInbox() {
    supplement.archive();
    assertIsArchived();
  }

  public void testUnmutedRemoteArchivedIsNotInbox() {
    substrate.archiveAtVersion(ROOT, (int) ROOT_VERSION);
    substrate.archiveAtVersion(W1, (int) W1_VERSION);
    assertIsArchived();
  }

  public void testUnfollowedIsNotInbox() {
    supplement.unfollow();
    assertIsUnfollowed();
  }

  public void testRemoteUnfollowedIsNotInbox() {
    substrate.unfollow();
    assertIsUnfollowed();
  }

  public void testArchiveArchivesAllWavelets() {
    supplement.archive();
    assertSubstrateArchiveVersionsEquals(EXPECTED_ARCHIVE_VERSIONS);
    assertIsArchived();
  }

  public void testChangeAfterArchiveIsInbox() {
    supplement.archive();
    wave.touch(ROOT);
    assertIsInbox();
  }

  public void testChangeAfterUnfollowIsNotInbox() {
    supplement.unfollow();
    wave.touch(ROOT);
    assertIsUnfollowed();
  }

  public void testUnfollowUnfollowsSubstrate() {
    supplement.unfollow();
    assertEquals(Boolean.FALSE, substrate.getFollowed());
    assertIsUnfollowed();
  }

  public void testMuteClearsArchiveVersions() {
    supplement.archive();
    supplement.mute();
    assertSubstrateArchiveVersionsEquals(Collections.<WaveletId, Long>emptyMap());
  }

  public void testArchiveDoesNotClearMuteNorSetsArchiveVersions() {
    supplement.unfollow();
    supplement.archive();
    assertEquals(Boolean.FALSE, substrate.getFollowed());
    assertSubstrateArchiveVersionsEquals(Collections.<WaveletId, Long> emptyMap());
  }

  //
  // Folder tests.
  //

  public void testMoveToFolderArchives() {
    supplement.moveToFolder(100);
    assertSubstrateArchiveVersionsEquals(EXPECTED_ARCHIVE_VERSIONS);
  }

  public void testMoveToFolderRemovesExistingFolders() {
    substrate.addFolder(100);
    substrate.addFolder(101);

    supplement.moveToFolder(102);

    assertEquals(supplement.getFolders(), Collections.singleton(102));
    assertSubstrateFoldersEquals(Collections.singleton(102));
  }

  public void testMoveToFolderIsNotInbox() {
    supplement.moveToFolder(100);
    assertFalse(supplement.isInbox());
  }

  public void testMoveToFolderPreservesUnfollow() {
    supplement.unfollow();
    supplement.moveToFolder(100);
    assertEquals(Boolean.FALSE, substrate.getFollowed());
  }

  public void testMoveToInboxFolderMovesToInbox() {
    supplement.moveToFolder(SupplementedWaveImpl.INBOX_FOLDER);
    assertTrue(supplement.isInbox());
    assertSubstrateFoldersEquals(Collections.<Integer>emptySet());
  }

  public void testMoveToInboxFolderRemovesExistingFolders() {
    supplement.moveToFolder(100);
    supplement.moveToFolder(SupplementedWaveImpl.INBOX_FOLDER);
    assertEquals(Collections.emptySet(), supplement.getFolders());
  }

  public void testInboxMovesToInbox() {
    supplement.inbox();
    assertIsInbox();
  }

  public void testInboxClearsArchiveState() {
    supplement.archive();
    supplement.inbox();

    assertSubstrateArchiveVersionsEquals(Collections.<WaveletId, Long>emptyMap());
  }

  public void testMoveToFolderAllArchivesAndClearsFolderState() {
    supplement.moveToFolder(100);
    supplement.moveToFolder(SupplementedWaveImpl.ALL_FOLDER);
    assertIsArchived();
    assertEquals(Collections.emptySet(), supplement.getFolders());
    assertSubstrateArchiveVersionsEquals(EXPECTED_ARCHIVE_VERSIONS);
    assertSubstrateFoldersEquals(Collections.<Integer>emptySet());
  }

  public void testMoveToFolderAllPreservesMute() {
    supplement.moveToFolder(100);
    supplement.unfollow();
    supplement.moveToFolder(SupplementedWaveImpl.ALL_FOLDER);
    assertEquals(Boolean.FALSE, substrate.getFollowed());
  }

  public void testMutePreservesFolders() {
    supplement.moveToFolder(100);
    supplement.mute();
    assertEquals(Collections.singleton(100), supplement.getFolders());
  }

  public void testParticipantReadState() {
    WaveletBasedConversation c = setUpWithWaveModel();
    Wavelet w = c.getWavelet();

    assertFalse(supplement.haveParticipantsEverBeenRead(w));
    assertTrue(supplement.isParticipantsUnread(w));

    supplement.markParticipantAsRead(w);
    assertTrue(supplement.haveParticipantsEverBeenRead(w));
    assertFalse(supplement.isParticipantsUnread(w));
  }

  public void testParticipantReadStateWithBlip() {
    WaveletBasedConversation c = setUpWithWaveModel();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    supplement.markParticipantAsRead(c.getWavelet());
  }

  public void testParticipantReadStateAffectedByWaveletReadState() {
    WaveletBasedConversation c = setUpWithWaveModel();
    Wavelet w = c.getWavelet();

    assertFalse(supplement.haveParticipantsEverBeenRead(w));
    assertTrue(supplement.isParticipantsUnread(w));

    supplement.markAsRead();
    assertTrue(supplement.haveParticipantsEverBeenRead(w));
    assertFalse(supplement.isParticipantsUnread(w));
  }

  public void testSeeMarksAsSeenAtVersion() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);

    final HashedVersion signature1 = HashedVersion.of(234L, new byte[] { 1 }),
        signature2 = HashedVersion.of(12828L, new byte[] { 2 });
    WaveletId waveletId1 = WaveletId.of("example.com", "somewaveletid1");
    when(supplementedView.getSignature(waveletId1)).thenReturn(signature1);

    WaveletId waveletId2 = WaveletId.of("example.com", "somewaveletid2");
    when(supplementedView.getSignature(waveletId2)).thenReturn(signature2);

    when(supplementedView.getWavelets()).thenReturn(Arrays.asList(waveletId1, waveletId2));

    SupplementedWaveImpl supplementedWave = new SupplementedWaveImpl(
        primitiveSupplement, supplementedView, DefaultFollow.ALWAYS);

    supplementedWave.see();

    verify(primitiveSupplement).setSeenVersion(eq(waveletId1), eq(signature1));
    verify(primitiveSupplement).setSeenVersion(eq(waveletId2), eq(signature2));

    // simulate the balancing get for the set we just verified above.
    when(primitiveSupplement.getSeenVersion(waveletId1)).thenReturn(signature1);
    when(primitiveSupplement.getSeenVersion(waveletId2)).thenReturn(signature2);

    assertEquals(signature1,  supplementedWave.getSeenVersion(waveletId1));
    assertEquals(signature2,  supplementedWave.getSeenVersion(waveletId2));
  }

  public void testGetSeenVersionReturnsSeenSignature() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);

    WaveletId waveletId1 = WaveletId.of("example.com", "somewaveletid1");
    HashedVersion wavelet1SeenVersion = HashedVersion.of(12312L, new byte[] { 1 });

    when(supplementedView.getWavelets()).thenReturn(Arrays.asList(waveletId1));
    when(primitiveSupplement.getSeenVersion(waveletId1)).thenReturn(
        wavelet1SeenVersion);

    SupplementedWaveImpl supplementedWave = new SupplementedWaveImpl(
        primitiveSupplement, supplementedView, DefaultFollow.ALWAYS);
    assertEquals(wavelet1SeenVersion, supplementedWave.getSeenVersion(waveletId1));
  }

  public void testTrashedIfWaveInTrash() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);
    when(primitiveSupplement.getFolders())
        .thenReturn(Arrays.asList(SupplementedWaveImpl.TRASH_FOLDER));

    assertTrue(new SupplementedWaveImpl(
        primitiveSupplement, supplementedView,DefaultFollow.ALWAYS)
        .isTrashed());
  }

  public void testNotTrashedIfWaveIsNotInTrash() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);
    when(primitiveSupplement.getFolders())
        .thenReturn(Arrays.asList(SupplementedWaveImpl.INBOX_FOLDER));

    assertFalse(new SupplementedWaveImpl(primitiveSupplement, supplementedView,
                                        DefaultFollow.ALWAYS)
        .isTrashed());
  }

  public void testHasBeenSeen() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);

    final HashedVersion signature1 = HashedVersion.of(234L, new byte[] { 1 });
    WaveletId waveletId1 = WaveletId.of("google.com", "somewaveletid1");
    when(supplementedView.getSignature(waveletId1)).thenReturn(signature1);

    when(supplementedView.getWavelets()).thenReturn(Arrays.asList(waveletId1));

    SupplementedWave supplementedWave =
        new SupplementedWaveImpl(primitiveSupplement, supplementedView, DefaultFollow.ALWAYS);

    assertFalse(supplementedWave.hasBeenSeen());

    supplementedWave.see();

    verify(primitiveSupplement).setSeenVersion(eq(waveletId1), eq(signature1));

    when(primitiveSupplement.getSeenVersion(waveletId1)).thenReturn(signature1);

    assertTrue(supplementedWave.hasBeenSeen());
  }

  public void testReadStateAffectedByTagsState() {
    WaveletBasedConversation c = setUpWithWaveModel();
    Wavelet w = c.getWavelet();

    assertTrue(supplement.isTagsUnread(w));

    addTags(w);
    assertTrue(supplement.isTagsUnread(w));

    supplement.markAsRead();
    assertFalse(supplement.isTagsUnread(w));

    supplement.markAsUnread();
    assertTrue(supplement.isTagsUnread(w));

    supplement.markTagsAsRead(w);
    assertFalse(supplement.isTagsUnread(w));
  }

  public void testParticipantReadStateAffectedByWaveletReadStateWithBlip() {
    WaveletBasedConversation c = setUpWithWaveModel();
    ObservableConversationThread t = c.getRootThread();
    ConversationBlip b = t.appendBlip();

    supplement.markAsRead();
  }

  public void testNewWaveHasNoPendingNotification() {
    assertFalse(supplement.hasPendingNotification());
  }

  public void testReportsPendingNotification() {
    substrate.setNotifiedVersion(W1, (int) W1_VERSION);
    assertTrue(supplement.hasPendingNotification());
  }

  public void testSeeingClearsPendingNotification() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);

    final byte[] SIGNATURE = new byte[] { 1 };
    final long VERSION_1 = 234L;
    final long VERSION_2 = 12828L;

    final HashedVersion signature1 = HashedVersion.of(VERSION_1, SIGNATURE),
        signature2 = HashedVersion.of(VERSION_2, SIGNATURE);
    WaveletId waveletId1 = WaveletId.of("example.com", "somewaveletid1");
    when(supplementedView.getSignature(waveletId1)).thenReturn(signature1);

    WaveletId waveletId2 = WaveletId.of("example.com", "somewaveletid2");
    when(supplementedView.getSignature(waveletId2)).thenReturn(signature2);

    when(supplementedView.getWavelets()).thenReturn(Arrays.asList(waveletId1, waveletId2));

    when(primitiveSupplement.getNotifiedWavelets())
        .thenReturn(CollectionUtils.immutableSet(waveletId1, waveletId2));
    when(primitiveSupplement.getSeenVersion(waveletId1))
        .thenReturn(HashedVersion.unsigned(0)).thenReturn(signature1);
    when(primitiveSupplement.getSeenVersion(waveletId2)).thenReturn(signature2);
    when(supplementedView.getVersion(waveletId1)).thenReturn(VERSION_1);
    when(supplementedView.getVersion(waveletId2)).thenReturn(VERSION_2);
    when(primitiveSupplement.getNotifiedVersion(waveletId1)).thenReturn((int) VERSION_1);
    when(primitiveSupplement.getNotifiedVersion(waveletId2)).thenReturn((int) VERSION_2);
    SupplementedWaveImpl supplementedWave = new SupplementedWaveImpl(
        primitiveSupplement, supplementedView, DefaultFollow.ALWAYS);

    supplementedWave.markAsNotified();

    verify(primitiveSupplement).setNotifiedVersion(eq(waveletId1), eq((int) VERSION_1));
    verify(primitiveSupplement).setNotifiedVersion(eq(waveletId2), eq((int) VERSION_2));

    assertTrue(supplementedWave.hasPendingNotification());

    supplementedWave.see();

    // Clears the deprecated pending-notification flag.
    verify(primitiveSupplement).clearPendingNotification();

    assertFalse(supplementedWave.hasPendingNotification());
  }

  public void testSeeingClearsPendingNotification_pendingNotificationFlagSet() {
    PrimitiveSupplement primitiveSupplement = mock(PrimitiveSupplement.class);
    SupplementWaveView supplementedView = mock(SupplementWaveView.class);

    final byte[] SIGNATURE = new byte[] { 1 };
    final long VERSION_1 = 234L;

    final HashedVersion signature1 = HashedVersion.of(VERSION_1, SIGNATURE);
    WaveletId waveletId1 = WaveletId.of("example.com", "somewaveletid1");
    when(supplementedView.getSignature(waveletId1)).thenReturn(signature1);
    when(primitiveSupplement.getNotifiedWavelets())
        .thenReturn(CollectionUtils.<WaveletId>immutableSet())
        .thenReturn(CollectionUtils.immutableSet(waveletId1));

    when(supplementedView.getWavelets()).thenReturn(Arrays.asList(waveletId1));

    // There is a legacy pending notification flag set.
    when(primitiveSupplement.getPendingNotification()).thenReturn(true);

    SupplementedWaveImpl supplementedWave = new SupplementedWaveImpl(
        primitiveSupplement, supplementedView, DefaultFollow.ALWAYS);
    assertTrue(supplementedWave.hasPendingNotification());

    when(primitiveSupplement.getSeenVersion(waveletId1))
        .thenReturn(HashedVersion.unsigned(0)).thenReturn(signature1);
    when(supplementedView.getVersion(waveletId1)).thenReturn(VERSION_1);
    when(primitiveSupplement.getNotifiedVersion(waveletId1)).thenReturn((int) VERSION_1);

    supplementedWave.markAsNotified();

    verify(primitiveSupplement).setNotifiedVersion(eq(waveletId1), eq((int) VERSION_1));

    assertTrue(supplementedWave.hasPendingNotification());

    supplementedWave.see();

    // Clears the deprecated pending-notification flag.
    verify(primitiveSupplement).clearPendingNotification();

    assertFalse(supplementedWave.hasPendingNotification());
  }

  //
  // Test helpers.
  //

  /**
   * Checks the archive versions in the supplement substrate.
   *
   * @param expected  expected archive versions
   */
  private void assertSubstrateArchiveVersionsEquals(Map<WaveletId, Long> expected) {
    Map<WaveletId, Long> actual = CollectionUtils.newHashMap();
    for (WaveletId wid : substrate.getArchiveWavelets()) {
      actual.put(wid, (longsubstrate.getArchiveWaveletVersion(wid));
    }

    assertEquals(expected, actual);
  }

  /**
   * Checks the folders in the supplement substrate.
   *
   * @param expected
   */
  private void assertSubstrateFoldersEquals(Set<Integer> expected) {
    Set<Integer> actual = CollectionUtils.newHashSet();
    for (Integer folder : substrate.getFolders()) {
      actual.add(folder);
    }

    assertEquals(expected, actual);
  }
}
TOP

Related Classes of org.waveprotocol.wave.model.supplement.SupplementedWaveImplTest

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.