• 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.annotation.SuppressLint;
8 import android.support.test.filters.SmallTest;
9 
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.base.test.util.UrlUtils;
17 import org.chromium.mojo.HandleMock;
18 import org.chromium.mojo.MojoTestRule;
19 import org.chromium.mojo.bindings.test.mojom.mojo.ConformanceTestInterface;
20 import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterface;
21 import org.chromium.mojo.bindings.test.mojom.mojo.IntegrationTestInterfaceTestHelper;
22 import org.chromium.mojo.system.Handle;
23 import org.chromium.mojo.system.impl.CoreImpl;
24 
25 import java.io.File;
26 import java.io.FileFilter;
27 import java.io.FileNotFoundException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Scanner;
31 
32 /**
33  * Testing validation upon deserialization using the interfaces defined in the
34  * mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom file.
35  * <p>
36  * One needs to pass '--test_data=bindings:{path to mojo/public/interfaces/bindings/tests/data}' to
37  * the test_runner script for this test to find the validation data it needs.
38  */
39 @RunWith(BaseJUnit4ClassRunner.class)
40 public class ValidationTest {
41     @Rule
42     public MojoTestRule mTestRule = new MojoTestRule();
43 
44     /**
45      * The path where validation test data is.
46      */
47     private static final File VALIDATION_TEST_DATA_PATH = new File(UrlUtils.getIsolatedTestFilePath(
48             "mojo/public/interfaces/bindings/tests/data/validation"));
49 
50     /**
51      * The data needed for a validation test.
52      */
53     private static class TestData {
54         public File dataFile;
55         public ValidationTestUtil.Data inputData;
56         public String expectedResult;
57     }
58 
59     private static class DataFileFilter implements FileFilter {
60         private final String mPrefix;
61 
DataFileFilter(String prefix)62         public DataFileFilter(String prefix) {
63             this.mPrefix = prefix;
64         }
65 
66         @Override
accept(File pathname)67         public boolean accept(File pathname) {
68             // TODO(yzshen, qsr): skip some interface versioning tests.
69             if (pathname.getName().startsWith("conformance_mthd13_good_2")) {
70                 return false;
71             }
72             return pathname.isFile() && pathname.getName().startsWith(mPrefix)
73                     && pathname.getName().endsWith(".data");
74         }
75     }
76 
77     @SuppressLint("NewApi")
getStringContent(File f)78     private static String getStringContent(File f) throws FileNotFoundException {
79         // TODO(crbug.com/635567): Fix this properly.
80         try (Scanner scanner = new Scanner(f)) {
81             scanner.useDelimiter("\\Z");
82             StringBuilder result = new StringBuilder();
83             while (scanner.hasNext()) {
84                 result.append(scanner.next());
85             }
86             return result.toString().trim();
87         }
88     }
89 
getTestData(String prefix)90     private static List<TestData> getTestData(String prefix) throws FileNotFoundException {
91         List<TestData> results = new ArrayList<TestData>();
92 
93         // Fail if the test data is not present.
94         if (!VALIDATION_TEST_DATA_PATH.isDirectory()) {
95             Assert.fail("No test data directory found. "
96                     + "Expected directory at: " + VALIDATION_TEST_DATA_PATH);
97         }
98 
99         File[] files = VALIDATION_TEST_DATA_PATH.listFiles(new DataFileFilter(prefix));
100         if (files != null) {
101             for (File dataFile : files) {
102                 File resultFile = new File(dataFile.getParent(),
103                         dataFile.getName().replaceFirst("\\.data$", ".expected"));
104                 TestData testData = new TestData();
105                 testData.dataFile = dataFile;
106                 testData.inputData = ValidationTestUtil.parseData(getStringContent(dataFile));
107                 testData.expectedResult = getStringContent(resultFile);
108                 results.add(testData);
109             }
110         }
111         return results;
112     }
113 
114     /**
115      * Runs all the test with the given prefix on the given {@link MessageReceiver}.
116      */
runTest(String prefix, MessageReceiver messageReceiver)117     private static void runTest(String prefix, MessageReceiver messageReceiver)
118             throws FileNotFoundException {
119         List<TestData> testData = getTestData(prefix);
120         for (TestData test : testData) {
121             Assert.assertNull("Unable to read: " + test.dataFile.getName() + ": "
122                             + test.inputData.getErrorMessage(),
123                     test.inputData.getErrorMessage());
124             List<Handle> handles = new ArrayList<Handle>();
125             for (int i = 0; i < test.inputData.getHandlesCount(); ++i) {
126                 handles.add(new HandleMock());
127             }
128             Message message = new Message(test.inputData.getData(), handles);
129             boolean passed = messageReceiver.accept(message);
130             if (passed && !test.expectedResult.equals("PASS")) {
131                 Assert.fail("Input: " + test.dataFile.getName()
132                         + ": The message should have been refused. Expected error: "
133                         + test.expectedResult);
134             }
135             if (!passed && test.expectedResult.equals("PASS")) {
136                 Assert.fail("Input: " + test.dataFile.getName()
137                         + ": The message should have been accepted.");
138             }
139         }
140     }
141 
142     private static class RoutingMessageReceiver implements MessageReceiver {
143         private final MessageReceiverWithResponder mRequest;
144         private final MessageReceiver mResponse;
145 
RoutingMessageReceiver( MessageReceiverWithResponder request, MessageReceiver response)146         private RoutingMessageReceiver(
147                 MessageReceiverWithResponder request, MessageReceiver response) {
148             this.mRequest = request;
149             this.mResponse = response;
150         }
151 
152         /**
153          * @see MessageReceiver#accept(Message)
154          */
155         @Override
accept(Message message)156         public boolean accept(Message message) {
157             try {
158                 MessageHeader header = message.asServiceMessage().getHeader();
159                 if (header.hasFlag(MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
160                     return mResponse.accept(message);
161                 } else {
162                     return mRequest.acceptWithResponder(message, new SinkMessageReceiver());
163                 }
164             } catch (DeserializationException e) {
165                 return false;
166             }
167         }
168 
169         /**
170          * @see MessageReceiver#close()
171          */
172         @Override
close()173         public void close() {}
174     }
175 
176     /**
177      * A trivial message receiver that refuses all messages it receives.
178      */
179     private static class SinkMessageReceiver implements MessageReceiverWithResponder {
180         @Override
accept(Message message)181         public boolean accept(Message message) {
182             return true;
183         }
184 
185         @Override
close()186         public void close() {}
187 
188         @Override
acceptWithResponder(Message message, MessageReceiver responder)189         public boolean acceptWithResponder(Message message, MessageReceiver responder) {
190             return true;
191         }
192     }
193 
194     /**
195      * Testing the conformance suite.
196      */
197     @Test
198     @SmallTest
testConformance()199     public void testConformance() throws FileNotFoundException {
200         runTest("conformance_",
201                 ConformanceTestInterface.MANAGER.buildStub(CoreImpl.getInstance(),
202                         ConformanceTestInterface.MANAGER.buildProxy(
203                                 CoreImpl.getInstance(), new SinkMessageReceiver())));
204     }
205 
206     /**
207      * Testing the integration suite for message headers.
208      */
209     @Test
210     @SmallTest
testIntegrationMessageHeader()211     public void testIntegrationMessageHeader() throws FileNotFoundException {
212         runTest("integration_msghdr_",
213                 new RoutingMessageReceiver(IntegrationTestInterface.MANAGER.buildStub(null,
214                                                    IntegrationTestInterface.MANAGER.buildProxy(
215                                                            null, new SinkMessageReceiver())),
216                         IntegrationTestInterfaceTestHelper
217                                 .newIntegrationTestInterfaceMethodCallback()));
218     }
219 
220     /**
221      * Testing the integration suite for request messages.
222      */
223     @Test
224     @SmallTest
testIntegrationRequestMessage()225     public void testIntegrationRequestMessage() throws FileNotFoundException {
226         runTest("integration_intf_rqst_",
227                 new RoutingMessageReceiver(IntegrationTestInterface.MANAGER.buildStub(null,
228                                                    IntegrationTestInterface.MANAGER.buildProxy(
229                                                            null, new SinkMessageReceiver())),
230                         IntegrationTestInterfaceTestHelper
231                                 .newIntegrationTestInterfaceMethodCallback()));
232     }
233 
234     /**
235      * Testing the integration suite for response messages.
236      */
237     @Test
238     @SmallTest
testIntegrationResponseMessage()239     public void testIntegrationResponseMessage() throws FileNotFoundException {
240         runTest("integration_intf_resp_",
241                 new RoutingMessageReceiver(IntegrationTestInterface.MANAGER.buildStub(null,
242                                                    IntegrationTestInterface.MANAGER.buildProxy(
243                                                            null, new SinkMessageReceiver())),
244                         IntegrationTestInterfaceTestHelper
245                                 .newIntegrationTestInterfaceMethodCallback()));
246     }
247 }
248