[tor-commits] [snowflake/master] Complete broker spec cases

serene at torproject.org serene at torproject.org
Wed Feb 10 22:04:10 UTC 2016


commit 4f18340c163c18d4bcad249b4e4976d3106cd014
Author: Serene Han <keroserene+git at gmail.com>
Date:   Wed Feb 10 13:05:21 2016 -0800

    Complete broker spec cases
---
 proxy/broker.coffee           | 67 +++++++++++++++---------------
 proxy/spec/broker.spec.coffee | 94 +++++++++++++++++++++++++++++++------------
 2 files changed, 102 insertions(+), 59 deletions(-)

diff --git a/proxy/broker.coffee b/proxy/broker.coffee
index 71fe6eb..e989d57 100644
--- a/proxy/broker.coffee
+++ b/proxy/broker.coffee
@@ -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
diff --git a/proxy/spec/broker.spec.coffee b/proxy/spec/broker.spec.coffee
index 3b47cd3..db936c1 100644
--- a/proxy/spec/broker.spec.coffee
+++ b/proxy/spec/broker.spec.coffee
@@ -19,32 +19,74 @@ describe 'Broker', ->
     expect(b.url).toEqual 'https://fake/'
     expect(b.id).not.toBeNull()
 
-  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()
-    poll = b.getClientOffer()
-    expect(poll).not.toBeNull()
-    poll.then (desc) =>
-      expect(desc).toEqual 'test'
-      done()
-
-  it 'requests correctly', ->
-    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()
+  describe 'getClientOffer', ->
+    it 'polls and promises a client offer', (done) ->
+      b = new Broker 'fake'
+      # 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()
+      expect(b._postRequest).toHaveBeenCalled()
+      poll.then (desc) ->
+        expect(desc).toEqual 'fake offer'
+        done()
+      .catch ->
+        fail 'should not reject on STATUS_OK'
+        done()
+
+    it 'rejects if the broker timed-out', (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 = 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()





More information about the tor-commits mailing list