1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.mojo.bindings; 6 7 import android.support.test.filters.SmallTest; 8 9 import org.junit.After; 10 import org.junit.Assert; 11 import org.junit.Rule; 12 import org.junit.Test; 13 import org.junit.runner.RunWith; 14 15 import org.chromium.base.test.BaseJUnit4ClassRunner; 16 import org.chromium.mojo.MojoTestRule; 17 import org.chromium.mojo.bindings.BindingsTestUtils.CapturingErrorHandler; 18 import org.chromium.mojo.bindings.test.mojom.imported.ImportedInterface; 19 import org.chromium.mojo.bindings.test.mojom.sample.Factory; 20 import org.chromium.mojo.bindings.test.mojom.sample.NamedObject; 21 import org.chromium.mojo.bindings.test.mojom.sample.NamedObject.GetNameResponse; 22 import org.chromium.mojo.bindings.test.mojom.sample.Request; 23 import org.chromium.mojo.bindings.test.mojom.sample.Response; 24 import org.chromium.mojo.system.DataPipe.ConsumerHandle; 25 import org.chromium.mojo.system.MessagePipeHandle; 26 import org.chromium.mojo.system.Pair; 27 import org.chromium.mojo.system.impl.CoreImpl; 28 29 import java.io.Closeable; 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.List; 33 34 /** 35 * Tests for interfaces / proxies / stubs generated for sample_factory.mojom. 36 */ 37 @RunWith(BaseJUnit4ClassRunner.class) 38 public class InterfacesTest { 39 @Rule 40 public MojoTestRule mTestRule = new MojoTestRule(); 41 42 private static final String OBJECT_NAME = "hello world"; 43 44 private final List<Closeable> mCloseablesToClose = new ArrayList<Closeable>(); 45 46 /** 47 * Basic implementation of {@link NamedObject}. 48 */ 49 public static class MockNamedObjectImpl extends CapturingErrorHandler implements NamedObject { 50 private String mName = ""; 51 52 /** 53 * @see org.chromium.mojo.bindings.Interface#close() 54 */ 55 @Override close()56 public void close() {} 57 58 @Override setName(String name)59 public void setName(String name) { 60 mName = name; 61 } 62 63 @Override getName(GetNameResponse callback)64 public void getName(GetNameResponse callback) { 65 callback.call(mName); 66 } 67 getNameSynchronously()68 public String getNameSynchronously() { 69 return mName; 70 } 71 } 72 73 /** 74 * Implementation of {@link GetNameResponse} keeping track of usage. 75 */ 76 public static class RecordingGetNameResponse implements GetNameResponse { 77 private String mName; 78 private boolean mCalled; 79 RecordingGetNameResponse()80 public RecordingGetNameResponse() { 81 reset(); 82 } 83 84 @Override call(String name)85 public void call(String name) { 86 mName = name; 87 mCalled = true; 88 } 89 getName()90 public String getName() { 91 return mName; 92 } 93 wasCalled()94 public boolean wasCalled() { 95 return mCalled; 96 } 97 reset()98 public void reset() { 99 mName = null; 100 mCalled = false; 101 } 102 } 103 104 /** 105 * Basic implementation of {@link Factory}. 106 */ 107 public class MockFactoryImpl extends CapturingErrorHandler implements Factory { 108 private boolean mClosed = false; 109 isClosed()110 public boolean isClosed() { 111 return mClosed; 112 } 113 114 /** 115 * @see org.chromium.mojo.bindings.Interface#close() 116 */ 117 @Override close()118 public void close() { 119 mClosed = true; 120 } 121 122 @Override doStuff(Request request, MessagePipeHandle pipe, DoStuffResponse callback)123 public void doStuff(Request request, MessagePipeHandle pipe, DoStuffResponse callback) { 124 if (pipe != null) { 125 pipe.close(); 126 } 127 Response response = new Response(); 128 response.x = 42; 129 callback.call(response, "Hello"); 130 } 131 132 @Override doStuff2(ConsumerHandle pipe, DoStuff2Response callback)133 public void doStuff2(ConsumerHandle pipe, DoStuff2Response callback) { 134 callback.call("World"); 135 } 136 137 @Override createNamedObject(InterfaceRequest<NamedObject> obj)138 public void createNamedObject(InterfaceRequest<NamedObject> obj) { 139 NamedObject.MANAGER.bind(new MockNamedObjectImpl(), obj); 140 } 141 142 @Override requestImportedInterface(InterfaceRequest<ImportedInterface> obj, RequestImportedInterfaceResponse callback)143 public void requestImportedInterface(InterfaceRequest<ImportedInterface> obj, 144 RequestImportedInterfaceResponse callback) { 145 throw new UnsupportedOperationException("Not implemented."); 146 } 147 148 @Override takeImportedInterface( ImportedInterface obj, TakeImportedInterfaceResponse callback)149 public void takeImportedInterface( 150 ImportedInterface obj, TakeImportedInterfaceResponse callback) { 151 throw new UnsupportedOperationException("Not implemented."); 152 } 153 } 154 155 /** 156 * Implementation of DoStuffResponse that keeps track of if the response is called. 157 */ 158 public static class DoStuffResponseImpl implements Factory.DoStuffResponse { 159 private boolean mResponseCalled = false; 160 wasResponseCalled()161 public boolean wasResponseCalled() { 162 return mResponseCalled; 163 } 164 165 @Override call(Response response, String string)166 public void call(Response response, String string) { 167 mResponseCalled = true; 168 } 169 } 170 171 /** 172 * @see MojoTestCase#tearDown() 173 */ 174 @After tearDown()175 public void tearDown() throws Exception { 176 // Close the elements in the reverse order they were added. This is needed because it is an 177 // error to close the handle of a proxy without closing the proxy first. 178 Collections.reverse(mCloseablesToClose); 179 for (Closeable c : mCloseablesToClose) { 180 c.close(); 181 } 182 } 183 184 /** 185 * Check that the given proxy receives the calls. If |impl| is not null, also check that the 186 * calls are forwared to |impl|. 187 */ checkProxy(NamedObject.Proxy proxy, MockNamedObjectImpl impl)188 private void checkProxy(NamedObject.Proxy proxy, MockNamedObjectImpl impl) { 189 RecordingGetNameResponse callback = new RecordingGetNameResponse(); 190 CapturingErrorHandler errorHandler = new CapturingErrorHandler(); 191 proxy.getProxyHandler().setErrorHandler(errorHandler); 192 193 if (impl != null) { 194 Assert.assertNull(impl.getLastMojoException()); 195 Assert.assertEquals("", impl.getNameSynchronously()); 196 } 197 198 proxy.getName(callback); 199 mTestRule.runLoopUntilIdle(); 200 201 Assert.assertNull(errorHandler.getLastMojoException()); 202 Assert.assertTrue(callback.wasCalled()); 203 Assert.assertEquals("", callback.getName()); 204 205 callback.reset(); 206 proxy.setName(OBJECT_NAME); 207 mTestRule.runLoopUntilIdle(); 208 209 Assert.assertNull(errorHandler.getLastMojoException()); 210 if (impl != null) { 211 Assert.assertNull(impl.getLastMojoException()); 212 Assert.assertEquals(OBJECT_NAME, impl.getNameSynchronously()); 213 } 214 215 proxy.getName(callback); 216 mTestRule.runLoopUntilIdle(); 217 218 Assert.assertNull(errorHandler.getLastMojoException()); 219 Assert.assertTrue(callback.wasCalled()); 220 Assert.assertEquals(OBJECT_NAME, callback.getName()); 221 } 222 223 @Test 224 @SmallTest testName()225 public void testName() { 226 Assert.assertEquals("sample.NamedObject", NamedObject.MANAGER.getName()); 227 } 228 229 @Test 230 @SmallTest testProxyAndStub()231 public void testProxyAndStub() { 232 MockNamedObjectImpl impl = new MockNamedObjectImpl(); 233 NamedObject.Proxy proxy = 234 NamedObject.MANAGER.buildProxy(null, NamedObject.MANAGER.buildStub(null, impl)); 235 236 checkProxy(proxy, impl); 237 } 238 239 @Test 240 @SmallTest testProxyAndStubOverPipe()241 public void testProxyAndStubOverPipe() { 242 MockNamedObjectImpl impl = new MockNamedObjectImpl(); 243 NamedObject.Proxy proxy = 244 BindingsTestUtils.newProxyOverPipe(NamedObject.MANAGER, impl, mCloseablesToClose); 245 246 checkProxy(proxy, impl); 247 } 248 249 @Test 250 @SmallTest testFactoryOverPipe()251 public void testFactoryOverPipe() { 252 Factory.Proxy proxy = BindingsTestUtils.newProxyOverPipe( 253 Factory.MANAGER, new MockFactoryImpl(), mCloseablesToClose); 254 Pair<NamedObject.Proxy, InterfaceRequest<NamedObject>> request = 255 NamedObject.MANAGER.getInterfaceRequest(CoreImpl.getInstance()); 256 mCloseablesToClose.add(request.first); 257 proxy.createNamedObject(request.second); 258 259 checkProxy(request.first, null); 260 } 261 262 @Test 263 @SmallTest testInterfaceClosing()264 public void testInterfaceClosing() { 265 MockFactoryImpl impl = new MockFactoryImpl(); 266 Factory.Proxy proxy = 267 BindingsTestUtils.newProxyOverPipe(Factory.MANAGER, impl, mCloseablesToClose); 268 269 Assert.assertFalse(impl.isClosed()); 270 271 proxy.close(); 272 mTestRule.runLoopUntilIdle(); 273 274 Assert.assertTrue(impl.isClosed()); 275 } 276 277 @Test 278 @SmallTest testResponse()279 public void testResponse() { 280 MockFactoryImpl impl = new MockFactoryImpl(); 281 Factory.Proxy proxy = 282 BindingsTestUtils.newProxyOverPipe(Factory.MANAGER, impl, mCloseablesToClose); 283 Request request = new Request(); 284 request.x = 42; 285 Pair<MessagePipeHandle, MessagePipeHandle> handles = 286 CoreImpl.getInstance().createMessagePipe(null); 287 DoStuffResponseImpl response = new DoStuffResponseImpl(); 288 proxy.doStuff(request, handles.first, response); 289 290 Assert.assertFalse(response.wasResponseCalled()); 291 292 mTestRule.runLoopUntilIdle(); 293 294 Assert.assertTrue(response.wasResponseCalled()); 295 } 296 } 297