Complete broker spec cases

This commit is contained in:
Serene Han 2016-02-10 13:05:21 -08:00
parent bb9eb721e2
commit 4f18340c16
2 changed files with 101 additions and 58 deletions

View file

@ -9,6 +9,9 @@ STATUS_OK = 200
STATUS_GONE = 410
STATUS_GATEWAY_TIMEOUT = 504
MESSAGE_TIMEOUT = 'Timed out waiting for a client offer.'
MESSAGE_UNEXPECTED = 'Unexpected status.'
genSnowflakeID = ->
Math.random().toString(36).substring(2)
@ -17,7 +20,6 @@ class Broker
clients: 0
id: null
request: null
# When interacting with the Broker, snowflake must generate a unique session
# ID so the Broker can keep track of which signalling channel it's speaking
@ -29,53 +31,35 @@ class Broker
@url = 'https://' + @url if 0 != @url.indexOf('https://', 0)
@url += '/' if '/' != @url.substr -1
# Snowflake registers with the broker using an HTTP POST request, and expects
# a response from the broker containing some client offer.
# Promises some client SDP Offer.
# Registers this Snowfalke with the broker using an HTTP POST request, and
# waits for a response containing some client offer that the Broker chooses
# for this proxy..
# TODO: Actually support multiple clients.
getClientOffer: =>
new Promise (fulfill, reject) =>
xhr = new XMLHttpRequest()
@request = xhr
@fulfill = fulfill
# @request.onreadystatechange = @processOffer
xhr.onreadystatechange = =>
xhr.onreadystatechange = ->
return if xhr.DONE != xhr.readyState
switch xhr.status
when STATUS_OK
fulfill xhr.responseText # Should contain offer.
when STATUS_GATEWAY_TIMEOUT
reject 'Timed out waiting for a client to serve.'
reject MESSAGE_TIMEOUT
else
log 'Broker ERROR: Unexpected ' + xhr.status +
' - ' + xhr.statusText
Status.set ' failure. Please refresh.'
@sendRequest()
sendRequest: =>
try
@request.open 'POST', @url + 'proxy'
@request.setRequestHeader('X-Session-ID', @id)
catch err
###
An exception happens here when, for example, NoScript allows the domain
on which the proxy badge runs, but not the domain to which it's trying
to make the HTTP request. The exception message is like "Component
returned failure code: 0x805e0006 [nsIXMLHttpRequest.open]" on Firefox.
###
log 'Broker: exception while connecting: ' + err.message
return
@request.send @id
snowflake.ui.setStatus ' failure. Please refresh.'
reject MESSAGE_UNEXPECTED
@_xhr = xhr # Used by spec to fake async Broker interaction
@_postRequest xhr, 'proxy', @id
# Assumes getClientOffer happened, and a WebRTC SDP answer has been generated.
# Sends it back to the broker, which passes it to back to the original client.
sendAnswer: (answer) ->
dbg @id + ' - Sending answer back to broker...\n'
dbg answer.sdp
xhr = new XMLHttpRequest()
try
xhr.open 'POST', @url + 'answer'
xhr.setRequestHeader('X-Session-ID', @id)
catch err
log 'Broker: exception while connecting: ' + err.message
return
xhr.onreadystatechange = ->
return if xhr.DONE != xhr.readyState
switch xhr.status
@ -87,5 +71,22 @@ class Broker
else
dbg 'Broker ERROR: Unexpected ' + xhr.status +
' - ' + xhr.statusText
Status.set ' failure. Please refresh.'
xhr.send JSON.stringify(answer)
snowflake.ui.setStatus ' failure. Please refresh.'
@_postRequest xhr, 'answer', JSON.stringify(answer)
# urlSuffix for the broker is different depending on what action
# is desired.
_postRequest: (xhr, urlSuffix, payload) =>
try
xhr.open 'POST', @url + urlSuffix
xhr.setRequestHeader('X-Session-ID', @id)
catch err
###
An exception happens here when, for example, NoScript allows the domain
on which the proxy badge runs, but not the domain to which it's trying
to make the HTTP xhr. The exception message is like "Component
returned failure code: 0x805e0006 [nsIXMLHttpRequest.open]" on Firefox.
###
log 'Broker: exception while connecting: ' + err.message
return
xhr.send payload

View file

@ -19,32 +19,74 @@ describe 'Broker', ->
expect(b.url).toEqual 'https://fake/'
expect(b.id).not.toBeNull()
describe 'getClientOffer', ->
it 'polls and promises a client offer', (done) ->
b = new Broker 'fake'
# fake successful request
spyOn(b, 'sendRequest').and.callFake ->
b.request.readyState = b.request.DONE
b.request.status = STATUS_OK
b.request.responseText = 'test'
b.request.onreadystatechange()
# fake successful request and response from broker.
spyOn(b, '_postRequest').and.callFake ->
b._xhr.readyState = b._xhr.DONE
b._xhr.status = STATUS_OK
b._xhr.responseText = 'fake offer'
b._xhr.onreadystatechange()
poll = b.getClientOffer()
expect(poll).not.toBeNull()
poll.then (desc) =>
expect(desc).toEqual 'test'
expect(b._postRequest).toHaveBeenCalled()
poll.then (desc) ->
expect(desc).toEqual 'fake offer'
done()
.catch ->
fail 'should not reject on STATUS_OK'
done()
it 'requests correctly', ->
it 'rejects if the broker timed-out', (done) ->
b = new Broker 'fake'
b.request = new XMLHttpRequest()
spyOn(b.request, 'open')
spyOn(b.request, 'setRequestHeader')
spyOn(b.request, 'send')
b.sendRequest()
expect(b.request.open).toHaveBeenCalled()
expect(b.request.setRequestHeader).toHaveBeenCalled()
expect(b.request.send).toHaveBeenCalled()
# fake timed-out request from broker
spyOn(b, '_postRequest').and.callFake ->
b._xhr.readyState = b._xhr.DONE
b._xhr.status = STATUS_GATEWAY_TIMEOUT
b._xhr.onreadystatechange()
poll = b.getClientOffer()
expect(poll).not.toBeNull()
expect(b._postRequest).toHaveBeenCalled()
poll.then (desc) ->
fail 'should not fulfill on GATEWAY_TIMEOUT'
done()
, (err) ->
expect(err).toBe MESSAGE_TIMEOUT
done()
it 'rejects on any other status', (done) ->
b = new Broker 'fake'
# fake timed-out request from broker
spyOn(b, '_postRequest').and.callFake ->
b._xhr.readyState = b._xhr.DONE
b._xhr.status = 1337
b._xhr.onreadystatechange()
poll = b.getClientOffer()
expect(poll).not.toBeNull()
expect(b._postRequest).toHaveBeenCalled()
poll.then (desc) ->
fail 'should not fulfill on non-OK status'
done()
, (err) ->
expect(err).toBe MESSAGE_UNEXPECTED
expect(b._xhr.status).toBe 1337
done()
it 'responds to the broker with answer', ->
# TODO: fix
b = new Broker 'fake'
b.sendAnswer 'foo'
spyOn(b, '_postRequest')
b.sendAnswer 123
expect(b._postRequest).toHaveBeenCalledWith(
jasmine.any(Object), 'answer', '123')
it 'POST XMLHttpRequests to the broker', ->
b = new Broker 'fake'
b._xhr = new XMLHttpRequest()
spyOn(b._xhr, 'open')
spyOn(b._xhr, 'setRequestHeader')
spyOn(b._xhr, 'send')
b._postRequest b._xhr, 'test', 'data'
expect(b._xhr.open).toHaveBeenCalled()
expect(b._xhr.setRequestHeader).toHaveBeenCalled()
expect(b._xhr.send).toHaveBeenCalled()