summaryrefslogtreecommitdiffstats
path: root/dom/system/gonk/tests/test_ril_worker_buf.js
blob: 30054a881512c058765694e9d325358a12a5bd16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

function run_test() {
  run_next_test();
}

/**
 * Add test function with specified parcel and request handler.
 *
 * @param parcel
 *        Incoming parcel to be tested.
 * @param handler
 *        Handler to be invoked as RIL request handler.
 */
function add_test_incoming_parcel(parcel, handler) {
  add_test(function test_incoming_parcel() {
    let worker = newWorker({
      postRILMessage: function(data) {
        // do nothing
      },
      postMessage: function(message) {
        // do nothing
      }
    });

    if (!parcel) {
      parcel = newIncomingParcel(-1,
                                 worker.RESPONSE_TYPE_UNSOLICITED,
                                 worker.REQUEST_VOICE_REGISTRATION_STATE,
                                 [0, 0, 0, 0]);
    }

    let context = worker.ContextPool._contexts[0];
    // supports only requests less or equal than UINT8_MAX(255).
    let buf = context.Buf;
    let request = parcel[buf.PARCEL_SIZE_SIZE + buf.UINT32_SIZE];
    context.RIL[request] = function ril_request_handler() {
      handler.apply(this, arguments);
    };

    worker.onRILMessage(0, parcel);

    // end of incoming parcel's trip, let's do next test.
    run_next_test();
  });
}

// Test normal parcel handling.
add_test_incoming_parcel(null,
  function test_normal_parcel_handling() {
    let self = this;
    try {
      // reads exactly the same size, should not throw anything.
      self.context.Buf.readInt32();
    } catch (e) {
      ok(false, "Got exception: " + e);
    }
  }
);

// Test parcel under read.
add_test_incoming_parcel(null,
  function test_parcel_under_read() {
    let self = this;
    try {
      // reads less than parcel size, should not throw.
      self.context.Buf.readUint16();
    } catch (e) {
      ok(false, "Got exception: " + e);
    }
  }
);

// Test parcel over read.
add_test_incoming_parcel(null,
  function test_parcel_over_read() {
    let buf = this.context.Buf;

    // read all data available
    while (buf.readAvailable > 0) {
      buf.readUint8();
    }

    throws(function over_read_handler() {
      // reads more than parcel size, should throw an error.
      buf.readUint8();
    },"Trying to read data beyond the parcel end!");
  }
);

// Test Bug 814761: buffer overwritten
add_test(function test_incoming_parcel_buffer_overwritten() {
  let worker = newWorker({
    postRILMessage: function(data) {
      // do nothing
    },
    postMessage: function(message) {
      // do nothing
    }
  });

  let context = worker.ContextPool._contexts[0];
  // A convenient alias.
  let buf = context.Buf;

  // Allocate an array of specified size and set each of its elements to value.
  function calloc(length, value) {
    let array = new Array(length);
    for (let i = 0; i < length; i++) {
      array[i] = value;
    }
    return array;
  }

  // Do nothing in handleParcel().
  let request = worker.REQUEST_VOICE_REGISTRATION_STATE;
  context.RIL[request] = null;

  // Prepare two parcels, whose sizes are both smaller than the incoming buffer
  // size but larger when combined, to trigger the bug.
  let pA_dataLength = buf.incomingBufferLength / 2;
  let pA = newIncomingParcel(-1,
                             worker.RESPONSE_TYPE_UNSOLICITED,
                             request,
                             calloc(pA_dataLength, 1));
  let pA_parcelSize = pA.length - buf.PARCEL_SIZE_SIZE;

  let pB_dataLength = buf.incomingBufferLength * 3 / 4;
  let pB = newIncomingParcel(-1,
                             worker.RESPONSE_TYPE_UNSOLICITED,
                             request,
                             calloc(pB_dataLength, 1));
  let pB_parcelSize = pB.length - buf.PARCEL_SIZE_SIZE;

  // First, send an incomplete pA and verifies related data pointer:
  let p1 = pA.subarray(0, pA.length - 1);
  worker.onRILMessage(0, p1);
  // The parcel should not have been processed.
  equal(buf.readAvailable, 0);
  // buf.currentParcelSize should have been set because incoming data has more
  // than 4 octets.
  equal(buf.currentParcelSize, pA_parcelSize);
  // buf.readIncoming should contains remaining unconsumed octets count.
  equal(buf.readIncoming, p1.length - buf.PARCEL_SIZE_SIZE);
  // buf.incomingWriteIndex should be ready to accept the last octet.
  equal(buf.incomingWriteIndex, p1.length);

  // Second, send the last octet of pA and whole pB. The Buf should now expand
  // to cover both pA & pB.
  let p2 = new Uint8Array(1 + pB.length);
  p2.set(pA.subarray(pA.length - 1), 0);
  p2.set(pB, 1);
  worker.onRILMessage(0, p2);
  // The parcels should have been both consumed.
  equal(buf.readAvailable, 0);
  // No parcel data remains.
  equal(buf.currentParcelSize, 0);
  // No parcel data remains.
  equal(buf.readIncoming, 0);
  // The Buf should now expand to cover both pA & pB.
  equal(buf.incomingWriteIndex, pA.length + pB.length);

  // end of incoming parcel's trip, let's do next test.
  run_next_test();
});

// Test Buf.readUint8Array.
add_test_incoming_parcel(null,
  function test_buf_readUint8Array() {
    let buf = this.context.Buf;

    let u8array = buf.readUint8Array(1);
    equal(u8array instanceof Uint8Array, true);
    equal(u8array.length, 1);
    equal(buf.readAvailable, 3);

    u8array = buf.readUint8Array(2);
    equal(u8array.length, 2);
    equal(buf.readAvailable, 1);

    throws(function over_read_handler() {
      // reads more than parcel size, should throw an error.
      u8array = buf.readUint8Array(2);
    }, "Trying to read data beyond the parcel end!");
  }
);