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