// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed 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 com.google.collide.client.collaboration; import com.google.collide.client.collaboration.IncomingDocOpDemultiplexer.Receiver; import com.google.collide.client.collaboration.cc.RevisionProvider; import com.google.collide.client.communication.MessageFilter; import com.google.collide.client.testing.MockFrontendApi; import com.google.collide.client.testing.MockFrontendApi.MockApi; import com.google.collide.dto.DocOp; import com.google.collide.dto.RecoverFromMissedDocOps; import com.google.collide.dto.RecoverFromMissedDocOpsResponse; import com.google.collide.dto.ServerToClientDocOp; import com.google.collide.dto.client.DtoClientImpls.ClientToServerDocOpImpl; import com.google.collide.dto.client.DtoClientImpls.DocOpImpl; import com.google.collide.dto.client.DtoClientImpls.MockRecoverFromMissedDocOpsResponseImpl; import com.google.collide.dto.client.DtoClientImpls.MockServerToClientDocOpImpl; import com.google.collide.dto.client.DtoClientImpls.RecoverFromMissedDocOpsImpl; import com.google.collide.dto.client.DtoClientImpls.RecoverFromMissedDocOpsResponseImpl; import com.google.collide.dto.client.DtoClientImpls.ServerToClientDocOpImpl; import com.google.collide.dto.client.ClientDocOpFactory; import com.google.collide.json.client.JsoArray; import com.google.collide.shared.ot.DocOpBuilder; import com.google.collide.shared.util.ErrorCallback; import com.google.collide.shared.util.Reorderer.TimeoutCallback; import junit.framework.Assert; /** * Test utilities for that are generally applicable to many different types of collaboration tests. */ public class CollaborationTestUtils { static class ReceiverListener implements DocOpReceiver.Listener<DocOp>, RevisionProvider { private int revision; ReceiverListener(int startingRevision) { revision = startingRevision; } @Override public int revision() { return revision; } @Override public void onMessage(int resultingRevision, String sid, DocOp mutation) { Assert.assertEquals(++revision, resultingRevision); } @Override public void onError(Throwable e) { Assert.fail(); } } static class Objects { final DocOpReceiver receiver; final IncomingDocOpDemultiplexer.Receiver transportSink; final MockLastClientToServerDocOpProvider sender; final DocOpRecoverer recoverer; final RevisionProvider version; final MockApi<RecoverFromMissedDocOps, RecoverFromMissedDocOpsResponse> api; final ReceiverListener receiverListener; public Objects(DocOpReceiver receiver, Receiver transportSink, MockApi<RecoverFromMissedDocOps, RecoverFromMissedDocOpsResponse> api, ReceiverListener receiverListener, MockLastClientToServerDocOpProvider sender, DocOpRecoverer recoverer, @SuppressWarnings("unused") MessageFilter messageFilter) { this.receiver = receiver; this.transportSink = transportSink; this.api = api; this.recoverer = recoverer; version = this.receiverListener = receiverListener; this.sender = sender; } } public static final String FILE_EDIT_SESSION_KEY = "2"; public static final ErrorCallback FAIL_ERROR_CALLBACK = new ErrorCallback() { @Override public void onError() { Assert.fail(); } }; public static final TimeoutCallback FAIL_TIMEOUT_CALLBACK = new TimeoutCallback() { @Override public void onTimeout(int lastVersionDispatched) { Assert.fail(); } }; static final DocOpImpl DOC_OP = (DocOpImpl) new DocOpBuilder(ClientDocOpFactory.INSTANCE, false).insert("a") .retainLine(1).build(); static ClientToServerDocOpImpl newOutgoingDocOpMsg(int version, int docOpCount) { return ClientToServerDocOpImpl.make() .setFileEditSessionKey(FILE_EDIT_SESSION_KEY) .setCcRevision(version) .setSelection(null) .setDocOps2(getRepeatedDocOps(docOpCount)); } static ServerToClientDocOpImpl newIncomingDocOpMsg(int appliedVersion) { return MockServerToClientDocOpImpl.make().setAppliedCcRevision(appliedVersion).setDocOp2(DOC_OP) .setFileEditSessionKey(FILE_EDIT_SESSION_KEY); } static RecoverFromMissedDocOpsImpl newRecoverMsg(int version, int unackedDocOpCount) { return RecoverFromMissedDocOpsImpl.make() .setCurrentCcRevision(version) .setDocOps2(getRepeatedDocOps(unackedDocOpCount)) .setFileEditSessionKey(FILE_EDIT_SESSION_KEY); } static RecoverFromMissedDocOpsResponseImpl newRecoverResponseMsg( int appliedVersion, int historyDocOpCount) { JsoArray<ServerToClientDocOp> docOpMsgs = JsoArray.create(); for (int i = 0; i < historyDocOpCount; i++) { docOpMsgs.add(MockServerToClientDocOpImpl.make() .setFileEditSessionKey(FILE_EDIT_SESSION_KEY) .setDocOp2(DOC_OP) .setAppliedCcRevision(appliedVersion++)); } return MockRecoverFromMissedDocOpsResponseImpl.make().setDocOps(docOpMsgs); } private static JsoArray<String> getRepeatedDocOps(int count) { JsoArray<String> docOps = JsoArray.create(); while (docOps.size() < count) { docOps.add(DOC_OP.serialize()); } return docOps; } static Objects createObjects( int startVersion, TimeoutCallback outOfOrderTimeoutCallback, int outOfOrderTimeoutMs) { MessageFilter messageFilter = new MessageFilter(); DocOpReceiver docOpReceiver = new DocOpReceiver( IncomingDocOpDemultiplexer.create(messageFilter), FILE_EDIT_SESSION_KEY, outOfOrderTimeoutCallback, outOfOrderTimeoutMs); MockApi<RecoverFromMissedDocOps, RecoverFromMissedDocOpsResponse> api = (MockApi<RecoverFromMissedDocOps, RecoverFromMissedDocOpsResponse>) new MockFrontendApi().RECOVER_FROM_MISSED_DOC_OPS; ReceiverListener receiverListener = new ReceiverListener(startVersion); docOpReceiver.setRevisionProvider(receiverListener); MockLastClientToServerDocOpProvider lastDocOpProvider = new MockLastClientToServerDocOpProvider(); DocOpRecoverer docOpRecoverer = new DocOpRecoverer(FILE_EDIT_SESSION_KEY, api, docOpReceiver, lastDocOpProvider, receiverListener); docOpReceiver.connect(startVersion, receiverListener); return new Objects(docOpReceiver, docOpReceiver.unorderedDocOpReceiver, api, receiverListener, lastDocOpProvider, docOpRecoverer, messageFilter); } }