Package org.waveprotocol.wave.client.wavepanel.block

Source Code of org.waveprotocol.wave.client.wavepanel.block.BlockStructureTestBase$NodeChecker

/**
* 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.client.wavepanel.block;


import junit.framework.TestCase;

import org.waveprotocol.wave.client.render.ConversationRenderer;
import org.waveprotocol.wave.client.render.RendererHelper;
import org.waveprotocol.wave.client.wavepanel.block.BlockStructure.Node;
import org.waveprotocol.wave.client.wavepanel.block.BlockStructure.NodeType;
import org.waveprotocol.wave.client.wavepanel.view.ModelIdMapperImpl;
import org.waveprotocol.wave.client.wavepanel.view.ViewIdMapper;
import org.waveprotocol.wave.model.conversation.Conversation;
import org.waveprotocol.wave.model.conversation.ConversationBlip;
import org.waveprotocol.wave.model.conversation.ConversationThread;
import org.waveprotocol.wave.model.conversation.ConversationView;
import org.waveprotocol.wave.model.conversation.testing.FakeConversationView;

/**
* Basic tests for a block structure.  Subclasses provude the structure to test.
*
*/
public abstract class BlockStructureTestBase extends TestCase {
  private ConversationView model;
  private BlockStructure bs;
  private ViewIdMapper viewIdMapper;

  @Override
  public void setUp() {
    model = createSample();
    viewIdMapper = new ViewIdMapper(ModelIdMapperImpl.create(model, "empty"));
    bs = create(model);
  }

  protected abstract BlockStructure create(ConversationView model);

  private static ConversationView createSample() {
    ConversationView v = FakeConversationView.builder().build();
    Conversation c = v.createRoot();
    ConversationThread root = c.getRootThread();
    sampleReply(root.appendBlip());
    root.appendBlip();
    root.appendBlip();
    biggerSampleReply(root.appendBlip());
    root.appendBlip();
    root.appendBlip();
    biggestSampleReply(root.appendBlip());
    root.appendBlip();
    biggerSampleReply(root.appendBlip());
    sampleReply(root.appendBlip());
    return v;
  }

  private static void sampleReply(ConversationBlip blip) {
    ConversationThread thread = blip.addReplyThread();
    thread.appendBlip();
    thread.appendBlip();
  }

  private static void biggerSampleReply(ConversationBlip blip) {
    ConversationThread thread = blip.addReplyThread();
    sampleReply(thread.appendBlip());
    sampleReply(thread.appendBlip());
    thread.appendBlip();
  }

  private static void biggestSampleReply(ConversationBlip blip) {
    ConversationThread thread = blip.addReplyThread();
    biggerSampleReply(thread.appendBlip());
    biggerSampleReply(thread.appendBlip());
    thread.appendBlip();
    thread.appendBlip();
  }


  public void testRootHasNoParent() {
    assertNull(bs.getRoot().getParent());
  }

  public void testIdMapping() {
    traverse(bs.getRoot(), new Visitor() {
      @Override
      public void visit(Node n) {
        assertSame(n, bs.getNode(n.getId()));
      }
    });
  }

  public void testStructureIsSelfConsistent() {
    traverse(bs.getRoot(), new Visitor() {
      @Override
      public void visit(Node n) {
        assertFirstChildSymmetry(n);
        assertLastChildSymmetry(n);
        assertNextSiblingSymmetry(n);
        assertPreviousSiblingSymmetry(n);
      }

    });
  }

  private static void assertFirstChildSymmetry(Node n) {
    Node c = n.getFirstChild();
    if (c != null) {
      assertSame(c.getParent(), n);
    }
  }

  private static void assertLastChildSymmetry(Node n) {
    Node c = n.getLastChild();
    if (c != null) {
      assertSame(c.getParent(), n);
    }
  }

  private static void assertNextSiblingSymmetry(Node n) {
    Node s = n.getNextSibling();
    if (s != null) {
      assertSame(s.getPreviousSibling(), n);
    }
  }

  private static void assertPreviousSiblingSymmetry(Node n) {
    Node s = n.getPreviousSibling();
    if (s != null) {
      assertSame(s.getNextSibling(), n);
    }
  }

  /**
   * Tests commutative nature of rendering, which produces homomorphic
   * structure. In layman's terms, tests that the rendering of X is composed of
   * the renderings of the components of X.
   */
  public void testNodeStructureReflectsRendering() {
    ConversationRenderer.renderWith(new NodeChecker(bs.getRoot()), model);
  }

  //
  //
  //

  /** Node visitor. */
  protected interface Visitor {
    void visit(Node n);
  }

  /** Notifies a visitor of every node in a subtree. */
  protected static void traverse(Node n, Visitor v) {
    if (n != null) {
      v.visit(n);
    }
    for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling()) {
      traverse(c, v);
    }
  }

  /**
   * Verifies that a block structure corresponds to a conversation rendering.
   */
  private class NodeChecker implements RendererHelper {
    private Node current;

    public NodeChecker(Node start) {
      current = start;
    }

    private void next() {
      assertNotNull(current);
      Node next;
      if ((next = current.getFirstChild()) != null) {
        current = next;
      } else {
        while (current != null && (next = current.getNextSibling()) == null) {
          current = current.getParent();
        }
        current = next;
      }
    }

    private void expect(NodeType type, String id) {
      next();
      assertNotNull(current);
      NodeType actualType = current.getType();
      String actualId = current.getId();
      assertEquals("unexpected type", type, actualType);
      assertEquals("unexpected id", id, actualId);
    }

    @Override
    public void startView(ConversationView view) {
      assertEquals(current.getType(), NodeType.ROOT);
    }

    @Override
    public void startConversation(Conversation conv) {
      expect(NodeType.CONVERSATION, viewIdMapper.conversationOf(conv));
      expect(NodeType.PARTICIPANTS, viewIdMapper.participantsOf(conv));
    }

    @Override
    public void startThread(ConversationThread thread) {
      expect(NodeType.THREAD, viewIdMapper.threadOf(thread));
    }

    @Override
    public void startInlineThread(ConversationThread thread) {
      expect(NodeType.THREAD, viewIdMapper.threadOf(thread));
    }

    @Override
    public void startBlip(ConversationBlip blip) {
      expect(NodeType.BLIP, viewIdMapper.blipOf(blip));
      expect(NodeType.META, viewIdMapper.metaOf(blip));
    }

    @Override
    public void endBlip(ConversationBlip blip) {
    }

    @Override
    public void endConversation(Conversation conv) {
    }

    @Override
    public void endInlineThread(ConversationThread thread) {
    }

    @Override
    public void endThread(ConversationThread thread) {
    }

    @Override
    public void endView(ConversationView view) {
      next();
      assertNull(current);
    }
  }
}
TOP

Related Classes of org.waveprotocol.wave.client.wavepanel.block.BlockStructureTestBase$NodeChecker

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.