Skip to content

Commit 39cebee

Browse files
committed
Merge remote-tracking branch 'origin/dev' into iislucas-separate-signal
Conflicts: Gruntfile.coffee package.json
2 parents f3adb51 + fbae14b commit 39cebee

File tree

9 files changed

+261
-31
lines changed

9 files changed

+261
-31
lines changed

Gruntfile.coffee

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ taskManager.add 'browserifySpecs', [
5353
'browserify:buildToolsTaskmanagerSpec'
5454
'browserify:loggingSpec'
5555
'browserify:loggingProviderSpec'
56-
'browserify:webrtcSpec'
56+
'browserify:peerconnectionSpec'
57+
'browserify:datachannelSpec'
58+
'browserify:queueSpec'
5759
]
5860

5961
# Create unit test code
@@ -64,7 +66,9 @@ taskManager.add 'browserifyCovSpecs', [
6466
'browserify:buildToolsTaskmanagerCovSpec'
6567
'browserify:loggingCovSpec'
6668
'browserify:loggingProviderCovSpec'
67-
'browserify:webrtcCovSpec'
69+
'browserify:peerconnectionCovSpec'
70+
'browserify:datachannelCovSpec'
71+
'browserify:queueCovSpec'
6872
]
6973

7074
# Run unit tests
@@ -76,6 +80,7 @@ taskManager.add 'unit_test', [
7680
'jasmine:logging'
7781
'jasmine:loggingProvider'
7882
'jasmine:webrtc'
83+
'jasmine:queue'
7984
]
8085

8186
# Run unit tests to produce coverage; these are separate from unit_tests because
@@ -88,6 +93,7 @@ taskManager.add 'coverage', [
8893
'jasmine:loggingCov'
8994
'jasmine:loggingProviderCov'
9095
'jasmine:webrtcCov'
96+
'jasmine:queueCov'
9197
]
9298

9399
# Run unit tests
@@ -211,6 +217,8 @@ module.exports = (grunt) ->
211217
loggingProviderCov: Rule.addCoverageToSpec(Rule.jasmineSpec 'loggingprovider')
212218
webrtc: Rule.jasmineSpec 'webrtc'
213219
webrtcCov: Rule.addCoverageToSpec(Rule.jasmineSpec 'webrtc')
220+
queue: Rule.jasmineSpec 'queue'
221+
queueCov: Rule.addCoverageToSpec(Rule.jasmineSpec 'queue')
214222

215223
browserify:
216224
# Browserify freedom-modules in the library
@@ -226,8 +234,12 @@ module.exports = (grunt) ->
226234
loggingProviderCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'loggingprovider/loggingprovider')
227235
loggingSpec: Rule.browserifySpec 'logging/logging'
228236
loggingCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'logging/logging')
229-
webrtcSpec: Rule.browserifySpec 'webrtc/peerconnection'
230-
webrtcCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'webrtc/peerconnection')
237+
peerconnectionSpec: Rule.browserifySpec 'webrtc/peerconnection'
238+
peerconnectionCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'webrtc/peerconnection')
239+
datachannelSpec: Rule.browserifySpec 'webrtc/datachannel'
240+
datachannelCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'webrtc/datachannel')
241+
queueSpec: Rule.browserifySpec 'queue/queue'
242+
queueCovSpec: Rule.addCoverageToBrowserify(Rule.browserifySpec 'queue/queue')
231243
# Browserify sample apps main freedom module and core environments
232244
copypasteFreedomChatFreedomModule: Rule.browserify 'samples/copypaste-freedom-chat/freedom-module'
233245
copypasteFreedomChatMain: Rule.browserify 'samples/copypaste-freedom-chat/main.core-env'

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "uproxy-lib",
33
"description": "Shared libraries for uProxy projects.",
4-
"version": "21.0.0",
4+
"version": "22.0.0",
55
"repository": {
66
"type": "git",
77
"url": "https://github.com/uProxy/uproxy-lib"

src/handler/queue.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
// CONSIDER: This is kind of similar to functional parsing. May be good to
2424
// formalize the relationship in comments here.
2525

26+
import baseQueue = require('../queue/queue');
27+
2628
// The |QueueFeeder| is the abstraction for events to be handled.
2729
export interface QueueFeeder<Feed,Result> {
2830
// Number of things in the queue to be handled.
@@ -160,7 +162,7 @@ class PendingPromiseHandler<T,T2> {
160162
export class Queue<Feed,Result>
161163
implements QueueFeeder<Feed,Result>, QueueHandler<Feed,Result> {
162164
// The queue of things to handle.
163-
private queue_ :PendingPromiseHandler<Feed, Result>[] = [];
165+
private queue_ = new baseQueue.Queue<PendingPromiseHandler<Feed, Result>>();
164166

165167
// Handler function for things on the queue. When null, things queue up.
166168
// When non-null, gets called on the thing to handle. When set, called on

src/queue/queue.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/// <reference path='../../../third_party/typings/jasmine/jasmine.d.ts' />
2+
3+
import queue = require('./queue');
4+
import Queue = queue.Queue;
5+
6+
describe('Base Queue', function() {
7+
var queue :Queue<string>;
8+
9+
beforeEach(() => {
10+
queue = new Queue<string>();
11+
});
12+
13+
it('New queue has length = 0', function() {
14+
expect(queue.length).toBe(0);
15+
});
16+
17+
it('3 items makes length = 3', function() {
18+
queue.push('A');
19+
queue.push('BB');
20+
queue.push('CCC');
21+
expect(queue.length).toBe(3);
22+
});
23+
24+
it('3 items and then clearing makes length = 0', function() {
25+
queue.push('A');
26+
queue.push('BB');
27+
queue.push('CCC');
28+
while (queue.length > 0) {
29+
queue.shift();
30+
}
31+
expect(queue.length).toBe(0);
32+
});
33+
34+
it('3 items come out in order', function() {
35+
queue.push('A');
36+
queue.push('BBB');
37+
queue.push('CCCCC');
38+
expect(queue.length).toBe(3);
39+
expect(queue.shift()).toEqual('A');
40+
expect(queue.length).toBe(2);
41+
expect(queue.shift()).toEqual('BBB');
42+
expect(queue.length).toBe(1);
43+
expect(queue.shift()).toEqual('CCCCC');
44+
expect(queue.length).toBe(0);
45+
});
46+
}); // describe('Base Queue', ... )

src/queue/queue.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// This file defines a basic queue data structure, providing
2+
// the standard Array push(), shift(), and length attributes,
3+
// but with O(1) operation.
4+
5+
// Private helper class.
6+
class Cell<T> {
7+
public next :Cell<T> = null;
8+
constructor(public item:T) {}
9+
}
10+
11+
export class Queue<T> {
12+
private back_ :Cell<T> = null;
13+
private front_ :Cell<T> = null;
14+
public length :number = 0;
15+
16+
constructor() {}
17+
18+
// Add an item to the back of the queue.
19+
public push = (item:T) : void => {
20+
var cell = new Cell<T>(item);
21+
if (this.length > 0) {
22+
this.back_.next = cell;
23+
} else {
24+
// The queue was empty, so set both pointers.
25+
this.front_ = cell;
26+
}
27+
this.back_ = cell;
28+
this.length++;
29+
}
30+
31+
// Remove and return the front element.
32+
public shift = () : T => {
33+
var dequeued = this.front_;
34+
// If this.front_ is this.back_, then getNext() returns null.
35+
this.front_ = dequeued.next;
36+
dequeued.next = null; // Just to help the garbage collector.
37+
this.length--;
38+
if (this.length === 0) {
39+
this.back_ = null;
40+
}
41+
return dequeued.item;
42+
}
43+
} // class Queue

src/webrtc/datachannel.spec.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/// <reference path='../../../third_party/typings/es6-promise/es6-promise.d.ts' />
2+
/// <reference path='../../../third_party/typings/jasmine/jasmine.d.ts' />
3+
/// <reference path="../../../third_party/freedom-typings/rtcpeerconnection.d.ts" />
4+
5+
import MockFreedomRtcDataChannel = require('../freedom/mocks/mock-rtcdatachannel');
6+
7+
import freedomMocker = require('../freedom/mocks/mock-freedom-in-module-env');
8+
freedom = freedomMocker.makeMockFreedomInModuleEnv({
9+
'rtcdatachannel': () => { return new MockFreedomRtcDataChannel(); }
10+
});
11+
12+
import datachannel = require('./datachannel');
13+
14+
describe('DataChannel', function() {
15+
var mockRtcDataChannel :MockFreedomRtcDataChannel;
16+
17+
beforeEach(function() {
18+
mockRtcDataChannel = new MockFreedomRtcDataChannel();
19+
});
20+
21+
// Ensure that close() waits for all outgoing unsent messages to be sent:
22+
// https://github.com/uProxy/uproxy/issues/1218
23+
it('close waits for all data to be sent', (done) => {
24+
// The core.rtcdatachannel is initially open.
25+
spyOn(mockRtcDataChannel, 'getReadyState').and.returnValue(
26+
Promise.resolve('open'));
27+
28+
// Have core.rtcdatachannel emit an onclose event when its
29+
// close() method is invoked.
30+
var closeSpy = spyOn(mockRtcDataChannel, 'close').and.callFake(() => {
31+
mockRtcDataChannel.handleEvent('onclose');
32+
});
33+
34+
// Pretend the core.rtcdatachannel is buffering a lot of data.
35+
// This will cause DataChannel to buffer sends.
36+
var getBufferedAmountSpy = spyOn(mockRtcDataChannel, 'getBufferedAmount');
37+
getBufferedAmountSpy.and.callFake(() => {
38+
return Promise.resolve(datachannel.PC_QUEUE_LIMIT);
39+
});
40+
41+
var sendBufferSpy = spyOn(mockRtcDataChannel, 'sendBuffer');
42+
43+
datachannel.createFromRtcDataChannel(mockRtcDataChannel).then(
44+
(channel:datachannel.DataChannel) => {
45+
channel.send({
46+
buffer: new Uint8Array([0, 1, 2]).buffer
47+
});
48+
49+
channel.close();
50+
51+
// At this point, our message should not yet have been sent.
52+
// Now that we've requested the channel be closed, "unblock" the
53+
// core.rtcdatachannel to drain the message queue.
54+
expect(sendBufferSpy).not.toHaveBeenCalled();
55+
getBufferedAmountSpy.and.returnValue(Promise.resolve(0));
56+
57+
channel.onceClosed.then(() => {
58+
expect(sendBufferSpy).toHaveBeenCalled();
59+
done();
60+
});
61+
});
62+
});
63+
});

0 commit comments

Comments
 (0)