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); |
+ } |
+} |