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