js_to_cpp_unittest.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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
5define('mojo/apps/js/test/js_to_cpp_unittest', [
6  'console',
7  'mojo/apps/js/test/js_to_cpp.mojom',
8  'mojo/public/js/bindings/connection',
9  'mojo/public/js/bindings/connector',
10  'mojo/public/js/bindings/core',
11], function (console, jsToCpp, connection, connector, core) {
12  var retainedConnection;
13  var sampleData;
14  var sampleMessage;
15  var BAD_VALUE = 13;
16  var DATA_PIPE_PARAMS = {
17    flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
18    elementNumBytes: 1,
19    capacityNumBytes: 64
20  };
21
22  function JsSideConnection(cppSide) {
23    this.cppSide_ = cppSide;
24    cppSide.startTest();
25  }
26
27  JsSideConnection.prototype = Object.create(jsToCpp.JsSideStub.prototype);
28
29  JsSideConnection.prototype.ping = function (arg) {
30    this.cppSide_.pingResponse();
31  };
32
33  JsSideConnection.prototype.echo = function (numIterations, arg) {
34    var dataPipe1;
35    var dataPipe2;
36    var i;
37    var messagePipe1;
38    var messagePipe2;
39    var specialArg;
40
41    // Ensure expected negative values are negative.
42    if (arg.si64 > 0)
43      arg.si64 = BAD_VALUE;
44
45    if (arg.si32 > 0)
46      arg.si32 = BAD_VALUE;
47
48    if (arg.si16 > 0)
49      arg.si16 = BAD_VALUE;
50
51    if (arg.si8 > 0)
52      arg.si8 = BAD_VALUE;
53
54    for (i = 0; i < numIterations; ++i) {
55      dataPipe1 = core.createDataPipe(DATA_PIPE_PARAMS);
56      dataPipe2 = core.createDataPipe(DATA_PIPE_PARAMS);
57      messagePipe1 = core.createMessagePipe();
58      messagePipe2 = core.createMessagePipe();
59
60      arg.data_handle = dataPipe1.consumerHandle;
61      arg.message_handle = messagePipe1.handle1;
62
63      specialArg = new jsToCpp.EchoArgs();
64      specialArg.si64 = -1;
65      specialArg.si32 = -1;
66      specialArg.si16 = -1;
67      specialArg.si8 = -1;
68      specialArg.name = 'going';
69      specialArg.data_handle = dataPipe2.consumerHandle;
70      specialArg.message_handle = messagePipe2.handle1;
71
72      writeDataPipe(dataPipe1, sampleData);
73      writeDataPipe(dataPipe2, sampleData);
74      writeMessagePipe(messagePipe1, sampleMessage);
75      writeMessagePipe(messagePipe2, sampleMessage);
76
77      this.cppSide_.echoResponse(createEchoArgsList(specialArg, arg));
78
79      core.close(dataPipe1.producerHandle);
80      core.close(dataPipe2.producerHandle);
81      core.close(messagePipe1.handle0);
82      core.close(messagePipe2.handle0);
83    }
84    this.cppSide_.testFinished();
85  };
86
87  JsSideConnection.prototype.bitFlip = function (arg) {
88    var iteration = 0;
89    var dataPipe;
90    var messagePipe;
91    var proto = connector.Connector.prototype;
92    var stopSignalled = false;
93
94    proto.realAccept = proto.accept;
95    proto.accept = function (message) {
96      var offset = iteration / 8;
97      var mask;
98      var value;
99      if (offset < message.buffer.arrayBuffer.byteLength) {
100        mask = 1 << (iteration % 8);
101        value = message.buffer.dataView.getUint8(offset) ^ mask;
102        message.buffer.dataView.setUint8(offset, value);
103        return this.realAccept(message);
104      }
105      stopSignalled = true;
106      return false;
107    };
108
109    while (!stopSignalled) {
110      dataPipe = core.createDataPipe(DATA_PIPE_PARAMS);
111      messagePipe = core.createMessagePipe();
112      writeDataPipe(dataPipe, sampleData);
113      writeMessagePipe(messagePipe, sampleMessage);
114      arg.data_handle = dataPipe.consumerHandle;
115      arg.message_handle = messagePipe.handle1;
116
117      this.cppSide_.bitFlipResponse(createEchoArgsList(arg));
118
119      core.close(dataPipe.producerHandle);
120      core.close(messagePipe.handle0);
121      iteration += 1;
122    }
123
124    proto.accept = proto.realAccept;
125    proto.realAccept = null;
126    this.cppSide_.testFinished();
127  };
128
129  JsSideConnection.prototype.backPointer = function (arg) {
130    var iteration = 0;
131    var dataPipe;
132    var messagePipe;
133    var proto = connector.Connector.prototype;
134    var stopSignalled = false;
135
136    proto.realAccept = proto.accept;
137    proto.accept = function (message) {
138      var delta = 8 * (1 + iteration % 32);
139      var offset = 8 * ((iteration / 32) | 0);
140      if (offset < message.buffer.arrayBuffer.byteLength - 4) {
141        message.buffer.dataView.setUint32(offset, 0x100000000 - delta, true);
142        message.buffer.dataView.setUint32(offset + 4, 0xffffffff, true);
143        return this.realAccept(message);
144      }
145      stopSignalled = true;
146      return false;
147    };
148
149    while (!stopSignalled) {
150      dataPipe = core.createDataPipe(DATA_PIPE_PARAMS);
151      messagePipe = core.createMessagePipe();
152      writeDataPipe(dataPipe, sampleData);
153      writeMessagePipe(messagePipe, sampleMessage);
154      arg.data_handle = dataPipe.consumerHandle;
155      arg.message_handle = messagePipe.handle1;
156
157      this.cppSide_.backPointerResponse(createEchoArgsList(arg));
158
159      core.close(dataPipe.producerHandle);
160      core.close(messagePipe.handle0);
161      iteration += 1;
162    }
163
164    proto.accept = proto.realAccept;
165    proto.realAccept = null;
166    this.cppSide_.testFinished();
167  };
168
169  function writeDataPipe(pipe, data) {
170    var writeResult = core.writeData(
171      pipe.producerHandle, data, core.WRITE_DATA_FLAG_ALL_OR_NONE);
172
173    if (writeResult.result != core.RESULT_OK) {
174      console.log('ERROR: Data pipe write result was ' + writeResult.result);
175      return false;
176    }
177    if (writeResult.numBytes != data.length) {
178      console.log('ERROR: Data pipe write length was ' + writeResult.numBytes);
179      return false;
180    }
181    return true;
182  }
183
184  function writeMessagePipe(pipe, arrayBuffer) {
185    var result = core.writeMessage(pipe.handle0, arrayBuffer, [], 0);
186    if (result != core.RESULT_OK) {
187      console.log('ERROR: Message pipe write result was ' + result);
188      return false;
189    }
190    return true;
191  }
192
193  function createEchoArgsListElement(item, next) {
194    var list = new jsToCpp.EchoArgsList();
195    list.item = item;
196    list.next = next;
197    return list;
198  }
199
200  function createEchoArgsList() {
201    var genuineArray = Array.prototype.slice.call(arguments);
202    return genuineArray.reduceRight(function (previous, current) {
203      return createEchoArgsListElement(current, previous);
204    }, null);
205  }
206
207  return function(handle) {
208    var i;
209    sampleData = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes);
210    for (i = 0; i < sampleData.length; ++i) {
211      sampleData[i] = i;
212    }
213    sampleMessage = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes);
214    for (i = 0; i < sampleMessage.length; ++i) {
215      sampleMessage[i] = 255 - i;
216    }
217    retainedConnection = new connection.Connection(handle, JsSideConnection,
218                                                   jsToCpp.CppSideProxy);
219  };
220});
221