| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 <!DOCTYPE html> | 
|  | 2 <script src="../resources/testharness.js"></script> | 
|  | 3 <script src="../resources/testharnessreport.js"></script> | 
|  | 4 <script src="../resources/mojo-helpers.js"></script> | 
|  | 5 <script src="resources/validation_test_input_parser.js"></script> | 
|  | 6 <script> | 
|  | 7 'use strict'; | 
|  | 8 | 
|  | 9 setup({ explicit_done: true }); | 
|  | 10 | 
|  | 11 define([ | 
|  | 12     'mojo/public/js/bindings', | 
|  | 13     'mojo/public/js/buffer', | 
|  | 14     'mojo/public/js/codec', | 
|  | 15     'mojo/public/js/core', | 
|  | 16     'mojo/resources/validation_test_input_parser', | 
|  | 17     'mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom', | 
|  | 18     'mojo/public/js/validator', | 
|  | 19 ], function(bindings, | 
|  | 20             buffer, | 
|  | 21             codec, | 
|  | 22             core, | 
|  | 23             parser, | 
|  | 24             testInterface, | 
|  | 25             validator) { | 
|  | 26 | 
|  | 27   var noError = validator.validationError.NONE; | 
|  | 28 | 
|  | 29   function checkData(data, expectedData, input) { | 
|  | 30     assert_equals(data.byteLength, expectedData.byteLength, | 
|  | 31         'message length (' + data.byteLength + ') doesn\'t match ' + | 
|  | 32         'expected length: ' + expectedData.byteLength + ' for ' + input); | 
|  | 33 | 
|  | 34     for (var i = 0; i < data.byteLength; i++) { | 
|  | 35       assert_equals(data.getUint8(i), expectedData.getUint8(i), | 
|  | 36           'message data mismatch at byte offset ' + i + 'for' + input); | 
|  | 37     } | 
|  | 38   } | 
|  | 39 | 
|  | 40   test(() => { | 
|  | 41     var input = '[f]+.3e9 [d]-10.03'; | 
|  | 42     var msg = parser.parseTestMessage(input); | 
|  | 43     var expectedData = new buffer.Buffer(12); | 
|  | 44     expectedData.setFloat32(0, +.3e9); | 
|  | 45     expectedData.setFloat64(4, -10.03); | 
|  | 46     checkData(msg.buffer, expectedData, input); | 
|  | 47   }, 'message parser: float items'); | 
|  | 48 | 
|  | 49   test(() => { | 
|  | 50     var input = '[u1]0x10// hello world !! \n\r  \t [u2]65535 \n' + | 
|  | 51         '[u4]65536 [u8]0xFFFFFFFFFFFFF 0 0Xff'; | 
|  | 52     var msg = parser.parseTestMessage(input); | 
|  | 53     var expectedData = new buffer.Buffer(17); | 
|  | 54     expectedData.setUint8(0, 0x10); | 
|  | 55     expectedData.setUint16(1, 65535); | 
|  | 56     expectedData.setUint32(3, 65536); | 
|  | 57     expectedData.setUint64(7, 0xFFFFFFFFFFFFF); | 
|  | 58     expectedData.setUint8(15, 0); | 
|  | 59     expectedData.setUint8(16, 0xff); | 
|  | 60     checkData(msg.buffer, expectedData, input); | 
|  | 61   }, 'message parser: unsigned integer items'); | 
|  | 62 | 
|  | 63   test(() => { | 
|  | 64     var input = '[s8]-0x800 [s1]-128\t[s2]+0 [s4]-40'; | 
|  | 65     var msg = parser.parseTestMessage(input); | 
|  | 66     var expectedData = new buffer.Buffer(15); | 
|  | 67     expectedData.setInt64(0, -0x800); | 
|  | 68     expectedData.setInt8(8, -128); | 
|  | 69     expectedData.setInt16(9, 0); | 
|  | 70     expectedData.setInt32(11, -40); | 
|  | 71     checkData(msg.buffer, expectedData, input); | 
|  | 72   }, 'message parser: signed integer items'); | 
|  | 73 | 
|  | 74   test(() => { | 
|  | 75     var input = '[b]00001011 [b]10000000  // hello world\n [b]00000000'; | 
|  | 76     var msg = parser.parseTestMessage(input); | 
|  | 77     var expectedData = new buffer.Buffer(3); | 
|  | 78     expectedData.setUint8(0, 11); | 
|  | 79     expectedData.setUint8(1, 128); | 
|  | 80     expectedData.setUint8(2, 0); | 
|  | 81     checkData(msg.buffer, expectedData, input); | 
|  | 82   }, 'message parser: byte items'); | 
|  | 83 | 
|  | 84   test(() => { | 
|  | 85     var input = '[dist4]foo 0 [dist8]bar 0 [anchr]foo [anchr]bar'; | 
|  | 86     var msg = parser.parseTestMessage(input); | 
|  | 87     var expectedData = new buffer.Buffer(14); | 
|  | 88     expectedData.setUint32(0, 14); | 
|  | 89     expectedData.setUint8(4, 0); | 
|  | 90     expectedData.setUint64(5, 9); | 
|  | 91     expectedData.setUint8(13, 0); | 
|  | 92     checkData(msg.buffer, expectedData, input); | 
|  | 93   }, 'message parser: anchors'); | 
|  | 94 | 
|  | 95   test(() => { | 
|  | 96     var input = '// This message has handles! \n[handles]50 [u8]2'; | 
|  | 97     var msg = parser.parseTestMessage(input); | 
|  | 98     var expectedData = new buffer.Buffer(8); | 
|  | 99     expectedData.setUint64(0, 2); | 
|  | 100 | 
|  | 101     assert_equals(msg.handleCount, 50, | 
|  | 102         'wrong handle count (' + msg.handleConut + ') for ' + input); | 
|  | 103     checkData(msg.buffer, expectedData, input); | 
|  | 104   }, 'message parser: handles'); | 
|  | 105 | 
|  | 106   test(() => { | 
|  | 107     var msg = parser.parseTestMessage(''); | 
|  | 108     assert_equals(msg.buffer.byteLength, 0, 'expected empty message for '); | 
|  | 109   }, 'message parser: empty input'); | 
|  | 110 | 
|  | 111   test(() => { | 
|  | 112     var input = '    \t  // hello world \n\r \t// the answer is 42   '; | 
|  | 113     var msg = parser.parseTestMessage(input); | 
|  | 114     assert_equals(msg.buffer.byteLength, 0, | 
|  | 115         'expected empty message for ' + input); | 
|  | 116   }, 'message parser: blank input'); | 
|  | 117 | 
|  | 118   test(() => { | 
|  | 119     function parserShouldFail(input) { | 
|  | 120       assert_throws(new parser.InputError(), function() { | 
|  | 121         parser.parseTestMessage(input); | 
|  | 122       }); | 
|  | 123     } | 
|  | 124 | 
|  | 125     ['/ hello world', | 
|  | 126      '[u1]x', | 
|  | 127      '[u2]-1000', | 
|  | 128      '[u1]0x100', | 
|  | 129      '[s2]-0x8001', | 
|  | 130      '[b]1', | 
|  | 131      '[b]1111111k', | 
|  | 132      '[dist4]unmatched', | 
|  | 133      '[anchr]hello [dist8]hello', | 
|  | 134      '[dist4]a [dist4]a [anchr]a', | 
|  | 135      // '[dist4]a [anchr]a [dist4]a [anchr]a', | 
|  | 136      '0 [handles]50' | 
|  | 137     ].forEach(parserShouldFail); | 
|  | 138   }, 'message parser: invalid input'); | 
|  | 139 | 
|  | 140   function fetchLite(url) { | 
|  | 141     return new Promise((resolve, reject) => { | 
|  | 142       var xhr = new XMLHttpRequest(); | 
|  | 143       xhr.open('GET', url); | 
|  | 144       xhr.onreadystatechange = () => { | 
|  | 145         if (xhr.readyState != 4) return; | 
|  | 146         resolve(xhr.responseText); | 
|  | 147       }; | 
|  | 148       xhr.send(); | 
|  | 149     }); | 
|  | 150   } | 
|  | 151 | 
|  | 152   function getMessageTestFiles(prefix) { | 
|  | 153     let genDirectory = '/gen/mojo/public/interfaces/bindings/tests/'; | 
|  | 154     return fetchLite(genDirectory + 'validation_files.txt').then((response) => { | 
|  | 155       assert_not_equals(response, null); | 
|  | 156       var testFiles = response.split('\n'); | 
|  | 157       assert_greater_than(testFiles.length, 0); | 
|  | 158       return testFiles.filter(function(s) { | 
|  | 159         return s.substr(-5) == '.data' && s.indexOf(prefix) == 0; | 
|  | 160       }).map(function(s) { | 
|  | 161         return genDirectory + 'data/validation/' + s.slice(0, -5); | 
|  | 162       }); | 
|  | 163     }); | 
|  | 164   } | 
|  | 165 | 
|  | 166   function readTestMessage(filename) { | 
|  | 167     return fetchLite(filename + '.data').then((response) => { | 
|  | 168       assert_not_equals(response, null); | 
|  | 169       return parser.parseTestMessage(response); | 
|  | 170     }); | 
|  | 171   } | 
|  | 172 | 
|  | 173   function readTestExpected(filename) { | 
|  | 174     return fetchLite(filename + '.expected').then((response) => { | 
|  | 175       assert_not_equals(response, null); | 
|  | 176       return response.trim(); | 
|  | 177     }); | 
|  | 178   } | 
|  | 179 | 
|  | 180   async function checkValidationResult(testFile, err) { | 
|  | 181     var actualResult = (err === noError) ? 'PASS' : err; | 
|  | 182     var expectedResult = await readTestExpected(testFile); | 
|  | 183     assert_equals(actualResult, expectedResult, | 
|  | 184         '[Test message validation failed: ' + testFile + ' ]'); | 
|  | 185   } | 
|  | 186 | 
|  | 187   async function testMessageValidation(prefix, filters) { | 
|  | 188     var testFiles = await getMessageTestFiles(prefix); | 
|  | 189     assert_greater_than(testFiles.length, 0); | 
|  | 190 | 
|  | 191     for (var i = 0; i < testFiles.length; i++) { | 
|  | 192       // TODO(hansmuller) Temporarily skipping array pointer overflow tests | 
|  | 193       // because JS numbers are limited to 53 bits. | 
|  | 194       // TODO(rudominer): Temporarily skipping 'no-such-method', | 
|  | 195       // 'invalid_request_flags', and 'invalid_response_flags' until additional | 
|  | 196       // logic in *RequestValidator and *ResponseValidator is ported from | 
|  | 197       // cpp to js. | 
|  | 198       // TODO(crbug/640298): Implement max recursion depth for JS. | 
|  | 199       // TODO(crbug/628104): Support struct map keys for JS. | 
|  | 200       if (testFiles[i].indexOf('overflow') != -1 || | 
|  | 201           testFiles[i].indexOf('conformance_mthd19') != -1 || | 
|  | 202           testFiles[i].indexOf('conformance_mthd20') != -1 || | 
|  | 203           testFiles[i].indexOf('no_such_method') != -1 || | 
|  | 204           testFiles[i].indexOf('invalid_request_flags') != -1 || | 
|  | 205           testFiles[i].indexOf('invalid_response_flags') != -1) { | 
|  | 206         console.log('[Skipping ' + testFiles[i] + ']'); | 
|  | 207         continue; | 
|  | 208       } | 
|  | 209 | 
|  | 210       var testMessage = await readTestMessage(testFiles[i]); | 
|  | 211       var handles = new Array(testMessage.handleCount); | 
|  | 212       var message = new codec.Message(testMessage.buffer, handles); | 
|  | 213       var messageValidator = new validator.Validator(message); | 
|  | 214 | 
|  | 215       var err = messageValidator.validateMessageHeader(); | 
|  | 216       for (var j = 0; err === noError && j < filters.length; ++j) | 
|  | 217         err = filters[j](messageValidator); | 
|  | 218 | 
|  | 219       await checkValidationResult(testFiles[i], err); | 
|  | 220     } | 
|  | 221   } | 
|  | 222 | 
|  | 223   promise_test(() => { | 
|  | 224     return testMessageValidation('conformance_', [ | 
|  | 225         testInterface.ConformanceTestInterface.validateRequest]); | 
|  | 226   }, 'conformance message validation'); | 
|  | 227 | 
|  | 228   promise_test(() => { | 
|  | 229     return testMessageValidation('boundscheck_', [ | 
|  | 230         testInterface.BoundsCheckTestInterface.validateRequest]); | 
|  | 231   }, 'bounds check message validation'); | 
|  | 232 | 
|  | 233   promise_test(() => { | 
|  | 234     return testMessageValidation('resp_conformance_', [ | 
|  | 235         testInterface.ConformanceTestInterface.validateResponse]); | 
|  | 236   }, 'response conformance message validation'); | 
|  | 237 | 
|  | 238   promise_test(() => { | 
|  | 239     return testMessageValidation('resp_boundscheck_', [ | 
|  | 240         testInterface.BoundsCheckTestInterface.validateResponse]); | 
|  | 241   }, 'response bounds check message validation'); | 
|  | 242 | 
|  | 243   async function testIntegratedMessageValidation(testFilesPattern, endpoint) { | 
|  | 244     var testFiles = await getMessageTestFiles(testFilesPattern); | 
|  | 245     assert_greater_than(testFiles.length, 0); | 
|  | 246 | 
|  | 247     var testMessagePipe = core.createMessagePipe(); | 
|  | 248     assert_equals(testMessagePipe.result, core.RESULT_OK); | 
|  | 249 | 
|  | 250     endpoint.bind(testMessagePipe.handle1); | 
|  | 251     var testingController = endpoint.enableTestingMode(); | 
|  | 252 | 
|  | 253     var validationError; | 
|  | 254     testingController.setInvalidIncomingMessageHandler(function(error) { | 
|  | 255       validationError = error; | 
|  | 256     }); | 
|  | 257 | 
|  | 258     for (var i = 0; i < testFiles.length; i++) { | 
|  | 259       validationError = noError; | 
|  | 260       var testMessage = await readTestMessage(testFiles[i]); | 
|  | 261       var handles = new Array(testMessage.handleCount); | 
|  | 262 | 
|  | 263       var writeMessageValue = core.writeMessage( | 
|  | 264           testMessagePipe.handle0, | 
|  | 265           new Uint8Array(testMessage.buffer.arrayBuffer), | 
|  | 266           new Array(testMessage.handleCount), | 
|  | 267           core.WRITE_MESSAGE_FLAG_NONE); | 
|  | 268       assert_equals(writeMessageValue, core.RESULT_OK); | 
|  | 269 | 
|  | 270       testingController.waitForNextMessage(); | 
|  | 271       await checkValidationResult(testFiles[i], validationError); | 
|  | 272     } | 
|  | 273 | 
|  | 274     assert_equals(core.close(testMessagePipe.handle0), core.RESULT_OK); | 
|  | 275   } | 
|  | 276 | 
|  | 277   promise_test(() => { | 
|  | 278     return testIntegratedMessageValidation( | 
|  | 279         'integration_msghdr', | 
|  | 280         new bindings.Binding(testInterface.IntegrationTestInterface, {})) | 
|  | 281       .then(() => { | 
|  | 282         return testIntegratedMessageValidation( | 
|  | 283             'integration_msghdr', | 
|  | 284             new testInterface.IntegrationTestInterfacePtr().ptr); | 
|  | 285       }); | 
|  | 286   }, 'integrated message header validation'); | 
|  | 287 | 
|  | 288   promise_test(() => { | 
|  | 289     return testIntegratedMessageValidation( | 
|  | 290         'integration_intf_rqst', | 
|  | 291         new bindings.Binding(testInterface.IntegrationTestInterface, {})); | 
|  | 292   }, 'integrated request message validation'); | 
|  | 293 | 
|  | 294   promise_test(() => { | 
|  | 295     return testIntegratedMessageValidation( | 
|  | 296         'integration_intf_resp', | 
|  | 297         new testInterface.IntegrationTestInterfacePtr().ptr); | 
|  | 298   }, 'integrated response message validation'); | 
|  | 299 | 
|  | 300   done(); | 
|  | 301 }); | 
|  | 302 | 
|  | 303 </script> | 
| OLD | NEW | 
|---|