Chromium Code Reviews| Index: mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java |
| diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..34bf0811dad6cc3f7dfb862a2fd2d1a6bd2d0595 |
| --- /dev/null |
| +++ b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java |
| @@ -0,0 +1,227 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.mojo.bindings; |
| + |
| +import android.test.suitebuilder.annotation.SmallTest; |
| + |
| +import org.chromium.mojo.MojoTestCase; |
| +import org.chromium.mojo.bindings.BindingsTestUtils.CapturingErrorHandler; |
| +import org.chromium.mojo.bindings.test.mojom.imported.ImportedInterface; |
| +import org.chromium.mojo.bindings.test.mojom.sample.Factory; |
| +import org.chromium.mojo.bindings.test.mojom.sample.FactoryClient; |
| +import org.chromium.mojo.bindings.test.mojom.sample.NamedObject; |
| +import org.chromium.mojo.bindings.test.mojom.sample.NamedObject.GetNameResponse; |
| +import org.chromium.mojo.bindings.test.mojom.sample.Request; |
| +import org.chromium.mojo.system.DataPipe.ConsumerHandle; |
| +import org.chromium.mojo.system.MessagePipeHandle; |
| +import org.chromium.mojo.system.Pair; |
| +import org.chromium.mojo.system.impl.CoreImpl; |
| + |
| +import java.io.Closeable; |
| +import java.util.ArrayList; |
| +import java.util.Collections; |
| +import java.util.List; |
| + |
| +/** |
| + * Testing interfaces generation. |
|
ppi
2014/08/21 14:47:13
If we don't want to impose a convention where the
qsr
2014/08/22 08:11:18
Done.
|
| + */ |
| +public class InterfacesTest extends MojoTestCase { |
| + |
| + private static final long RUN_LOOP_TIMEOUT_MS = 25; |
| + |
| + private final List<Closeable> mCloseableToClose = new ArrayList<Closeable>(); |
|
ppi
2014/08/21 14:47:14
nit: s/mCloseableToClose/mCloseablesToClose/
qsr
2014/08/22 08:11:18
Done.
|
| + |
| + /** |
| + * Basic implementation of {@link NamedObject}. |
| + */ |
| + public static class NamedObjectImpl extends CapturingErrorHandler implements NamedObject { |
|
rmcilroy
2014/08/21 14:43:52
MockNamedObjectImpl? (and similarly for all below)
qsr
2014/08/22 08:11:17
Done.
|
| + |
| + private String mName; |
| + |
| + @Override |
| + public void setName(String name) { |
| + mName = name; |
| + } |
| + |
| + @Override |
| + public void getName(GetNameResponse callback) { |
| + callback.call(mName); |
| + } |
| + |
| + public String getNameSynchronously() { |
| + return mName; |
| + } |
| + } |
| + |
| + /** |
| + * Implementation of {@link GetNameResponse} keeping track of usage. |
| + */ |
| + public static class RecordingGetNameResponse implements GetNameResponse { |
| + private String mName; |
| + private boolean mCalled; |
| + |
| + public RecordingGetNameResponse() { |
| + reset(); |
| + } |
| + |
| + @Override |
| + public void call(String name) { |
| + mName = name; |
| + mCalled = true; |
| + } |
| + |
| + public String getName() { |
| + return mName; |
| + } |
| + |
| + public boolean isCalled() { |
|
ppi
2014/08/21 14:47:14
nit: s/is/was/
qsr
2014/08/22 08:11:18
Done.
|
| + return mCalled; |
| + } |
| + |
| + public void reset() { |
| + mName = null; |
| + mCalled = false; |
| + } |
| + } |
| + |
| + /** |
| + * Basic implementation of {@link Factory}. |
| + */ |
| + public static class FactoryImpl extends CapturingErrorHandler implements Factory { |
| + |
| + @Override |
| + public void setClient(FactoryClient client) { |
| + } |
| + |
| + @Override |
| + public void doStuff(Request request, MessagePipeHandle pipe) { |
| + throw new UnsupportedOperationException("Not implemented."); |
| + } |
| + |
| + @Override |
| + public void doStuff2(ConsumerHandle pipe) { |
| + throw new UnsupportedOperationException("Not implemented."); |
| + } |
| + |
| + @Override |
| + public void createNamedObject(InterfaceRequest<NamedObject.Proxy> obj) { |
|
ppi
2014/08/21 14:47:13
I wonder if we should care that in C++ bindings we
qsr
2014/08/22 08:11:17
Done.
|
| + NamedObject.BUILDER.bind(obj, new NamedObjectImpl()); |
| + } |
| + |
| + @Override |
| + public void requestImportedInterface(InterfaceRequest<ImportedInterface.Proxy> obj, |
| + RequestImportedInterfaceResponse callback) { |
| + throw new UnsupportedOperationException("Not implemented."); |
| + } |
| + |
| + @Override |
| + public void takeImportedInterface(ImportedInterface obj, |
| + TakeImportedInterfaceResponse callback) { |
| + throw new UnsupportedOperationException("Not implemented."); |
| + } |
| + } |
| + |
| + /** |
| + * @see org.chromium.mojo.MojoTestCase#tearDown() |
| + */ |
| + @Override |
| + protected void tearDown() throws Exception { |
| + // Close the elements in the reverse order they were added. This is needed because it is an |
| + // error to close the handle of a proxy without closing the proxy first. |
| + Collections.reverse(mCloseableToClose); |
| + for (Closeable c : mCloseableToClose) { |
| + c.close(); |
| + } |
| + } |
| + |
| + private void addToCloseable(Pair<? extends Closeable, ? extends Closeable> pair) { |
|
ppi
2014/08/21 14:47:14
nit: s/addToCloseable/addCloseables/ maybe?
qsr
2014/08/22 08:11:17
Done.
|
| + mCloseableToClose.add(pair.first); |
| + mCloseableToClose.add(pair.second); |
| + } |
| + |
| + private Pair<MessagePipeHandle, MessagePipeHandle> newHandles() { |
| + Pair<MessagePipeHandle, MessagePipeHandle> result = |
| + CoreImpl.getInstance().createMessagePipe(null); |
| + addToCloseable(result); |
| + return result; |
| + } |
| + |
| + private <I extends Interface, P extends Interface.Proxy> P newProxyOverPipes( |
|
ppi
2014/08/21 14:47:14
nit: s/OverPipes/OverPipe/
qsr
2014/08/22 08:11:18
Done.
|
| + Interface.Builder<I, P> builder, I impl) { |
| + Pair<MessagePipeHandle, MessagePipeHandle> handles = newHandles(); |
| + P proxy = builder.connect(handles.first); |
| + mCloseableToClose.add(proxy); |
| + builder.bind(handles.second, impl); |
| + return proxy; |
| + } |
| + |
| + /** |
| + * Check that the given proxy receives the calls. If |impl| is not null, also check that the |
| + * calls are forwared to |impl|. |
| + */ |
| + private void checkProxy(NamedObject.Proxy proxy, NamedObjectImpl impl) { |
| + final String NAME = "hello world"; |
| + RecordingGetNameResponse callback = new RecordingGetNameResponse(); |
| + CapturingErrorHandler errorHandler = new CapturingErrorHandler(); |
| + proxy.setErrorHandler(errorHandler); |
| + |
| + if (impl != null) { |
| + assertNull(impl.getLastMojoException()); |
| + assertNull(impl.getNameSynchronously()); |
| + } |
| + |
| + proxy.getName(callback); |
| + nativeRunLoop(RUN_LOOP_TIMEOUT_MS); |
| + |
| + assertNull(errorHandler.getLastMojoException()); |
| + assertTrue(callback.isCalled()); |
| + assertNull(callback.getName()); |
| + |
| + callback.reset(); |
| + proxy.setName(NAME); |
| + nativeRunLoop(RUN_LOOP_TIMEOUT_MS); |
| + |
| + assertNull(errorHandler.getLastMojoException()); |
| + if (impl != null) { |
| + assertNull(impl.getLastMojoException()); |
| + assertEquals(NAME, impl.getNameSynchronously()); |
| + } |
| + |
| + proxy.getName(callback); |
| + nativeRunLoop(RUN_LOOP_TIMEOUT_MS); |
| + |
| + assertNull(errorHandler.getLastMojoException()); |
| + assertTrue(callback.isCalled()); |
| + assertEquals(NAME, callback.getName()); |
| + } |
| + |
| + @SmallTest |
| + public void testProxyAndStub() { |
| + NamedObjectImpl impl = new NamedObjectImpl(); |
| + NamedObject.Proxy proxy = |
| + NamedObject.BUILDER.buildProxy(null, NamedObject.BUILDER.buildStub(null, impl)); |
| + |
| + checkProxy(proxy, impl); |
| + } |
| + |
| + @SmallTest |
| + public void testProxyAndStubOverPipe() { |
| + NamedObjectImpl impl = new NamedObjectImpl(); |
| + NamedObject.Proxy proxy = newProxyOverPipes(NamedObject.BUILDER, impl); |
| + |
| + checkProxy(proxy, impl); |
| + } |
| + |
| + @SmallTest |
| + public void testFactoryOverPipe() { |
| + Factory.Proxy proxy = newProxyOverPipes(Factory.BUILDER, new FactoryImpl()); |
| + Pair<NamedObject.Proxy, InterfaceRequest<NamedObject.Proxy>> request = |
| + NamedObject.BUILDER.getInterfaceRequest(CoreImpl.getInstance()); |
| + addToCloseable(request); |
| + proxy.createNamedObject(request.second); |
| + |
| + checkProxy(request.first, null); |
| + } |
| +} |