[tor-commits] [snowflake/master] convert all coffeescript tests to jasmine

serene at torproject.org serene at torproject.org
Sun Feb 7 01:29:25 UTC 2016


commit e38bed8be3f876da5c840710f82a2f5e6b67ecc5
Author: Serene Han <keroserene+git at gmail.com>
Date:   Thu Feb 4 14:13:03 2016 -0800

    convert all coffeescript tests to jasmine
---
 .gitignore                  |   1 +
 .travis.yml                 |   2 +-
 proxy/Cakefile              |  23 ++--
 proxy/README.md             |   9 +-
 proxy/snowflake.coffee      |   4 +-
 proxy/snowflake_test.coffee | 323 --------------------------------------------
 proxy/spec.coffee           | 180 ++++++++++++++++++++++++
 proxy/websocket.coffee      |   1 +
 8 files changed, 205 insertions(+), 338 deletions(-)

diff --git a/.gitignore b/.gitignore
index 516f3ff..b1db25c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,5 @@ snowflake.log
 proxy/test
 proxy/build
 proxy/node_modules
+proxy/spec
 ignore/
diff --git a/.travis.yml b/.travis.yml
index c860b37..4a7aedd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,7 @@ go:
     - 1.5
 
 before_script:
-    npm install -g coffee-script coffeelint
+    npm install -g coffee-script coffeelint jasmine
 
 script:
     - make check
diff --git a/proxy/Cakefile b/proxy/Cakefile
index fc92934..c569110 100644
--- a/proxy/Cakefile
+++ b/proxy/Cakefile
@@ -11,10 +11,10 @@ FILES = [
   'ui.coffee'
   'snowflake.coffee'
 ]
-FILES_TEST = [
-  'snowflake_test.coffee'
+FILES_SPEC = [
+  'spec.coffee'
 ]
-FILES_ALL = FILES.concat FILES_TEST
+FILES_ALL = FILES.concat FILES_SPEC
 OUTFILE = 'build/snowflake.coffee'
 STATIC = 'static'
 
@@ -23,16 +23,18 @@ concatCoffeeFiles = -> exec 'cat ' + FILES.join(' ') + ' | cat > ' + OUTFILE
 copyStaticFiles = -> exec 'cp ' + STATIC + '/* build/'
 
 compileCoffee = ->
-  exec 'coffee -o build -c build/snowflake.coffee', (err, stdout, stderr) ->
+  exec 'coffee -o build -b -c build/snowflake.coffee', (err, stdout, stderr) ->
     throw err if err
 
 task 'test', 'snowflake unit tests', ->
-  exec 'mkdir -p test'
-  testFile = 'test/snowflake.bundle.coffee'
-  exec 'cat ' + FILES.join(' ') + ' snowflake_test.coffee | cat > ' + testFile
-  exec 'coffee ' + testFile + ' -v', (err, stdout, stderr) ->
-    throw err if err
-    console.log stdout + stderr
+  exec 'jasmine init >&-'
+  jasmineFiles = FILES.concat FILES_SPEC
+  outFile = 'spec/snowflake.bundle.coffee'
+  exec 'cat ' + jasmineFiles.join(' ') +  ' | cat > ' + outFile
+  exec 'coffee -o spec -cb ' + outFile
+  spawn 'jasmine', ['spec/snowflake.bundle.js'], {
+    stdio: 'inherit'
+  }
 
 task 'build', 'build the snowflake proxy', ->
   exec 'mkdir -p build'
@@ -49,4 +51,5 @@ task 'lint', 'ensure idiomatic coffeescript', ->
 
 task 'clean', 'remove all built files', ->
   exec 'rm -r build'
+  exec 'rm -r spec'
   exec 'rm -r test/snowflake.bundle.coffee'
diff --git a/proxy/README.md b/proxy/README.md
index 1affaca..364ac0e 100644
--- a/proxy/README.md
+++ b/proxy/README.md
@@ -2,12 +2,16 @@ This is the browser proxy component of Snowflake.
 
 ### Testing:
 
-Unit tests are available with:
+Unit testing with Jasmine are available with:
 ```
 cake test
 ```
+Requires jasmine. (`npm install -g jasmine`)
 
-To run locally, start a webserver and navigate to `snowflake.html`.
+To run locally, either:
+- Navigate to `proxy/build/embed.html`
+- For a more fully featured "debug" version,
+  start a webserver and navigate to `snowflake.html`.
 
 ### Parameters
 
@@ -16,7 +20,6 @@ snowflake uses the default relay `192.81.135.242:9901` and
 uses automatic signaling with the default broker at
 `https://snowflake-reg.appspot.com/`.
 
-
 Here are optional parameters to include in the query string.
 ```
 manual - enables copy-paste signalling mode.
diff --git a/proxy/snowflake.coffee b/proxy/snowflake.coffee
index 74f6a6e..eea1518 100644
--- a/proxy/snowflake.coffee
+++ b/proxy/snowflake.coffee
@@ -15,10 +15,12 @@ COPY_PASTE_ENABLED = false
 
 DEBUG = false
 query = null
-if window && window.location
+if 'undefined' != typeof window && window.location
   query = Query.parse(window.location.search.substr(1))
   DEBUG = Params.getBool(query, 'debug', false)
   COPY_PASTE_ENABLED = Params.getBool(query, 'manual', false)
+else
+  window = {}
 # HEADLESS is true if we are running not in a browser with a DOM.
 HEADLESS = 'undefined' == typeof(document)
 
diff --git a/proxy/snowflake_test.coffee b/proxy/snowflake_test.coffee
deleted file mode 100644
index 624257a..0000000
--- a/proxy/snowflake_test.coffee
+++ /dev/null
@@ -1,323 +0,0 @@
-window = {}
-ui = {}
-
-VERBOSE = false
-VERBOSE = true if process.argv.indexOf('-v') >= 0
-
-numTests = 0
-numFailed = 0
-
-announce = (testName) ->
-  console.log '\n --- ' + testName + ' ---' if VERBOSE
-
-pass = (test) ->
-  numTests++
-  console.log 'PASS ' + test if VERBOSE
-
-fail = (test, expected, actual) ->
-  numTests++
-  numFailed++
-  console.log 'FAIL ' + test +
-    '  expected: ' + JSON.stringify(expected) +
-    '  actual: ' + JSON.stringify(actual)
-
-# Stubs for browser functionality.
-class WebSocket
-  OPEN: 1
-  CLOSED: 0
-
-testBuildUrl = ->
-  TESTS = [{
-      args: ['http', 'example.com']
-      expected: 'http://example.com'
-    },{
-      args: ['http', 'example.com', 80]
-      expected: 'http://example.com'
-    },{
-      args: ['http', 'example.com', 81],
-      expected: 'http://example.com:81'
-    },{
-      args: ['https', 'example.com', 443]
-      expected: 'https://example.com'
-    },{
-      args: ['https', 'example.com', 444]
-      expected: 'https://example.com:444'
-    },{
-      args: ['http', 'example.com', 80, '/']
-      expected: 'http://example.com/'
-    },{
-      args: ['http', 'example.com', 80, '/test?k=%#v']
-      expected: 'http://example.com/test%3Fk%3D%25%23v'
-    },{
-      args: ['http', 'example.com', 80, '/test', []]
-      expected: 'http://example.com/test?'
-    },{
-      args: ['http', 'example.com', 80, '/test', [['k', '%#v']]]
-      expected: 'http://example.com/test?k=%25%23v'
-    },{
-      args: ['http', 'example.com', 80, '/test', [['a', 'b'], ['c', 'd']]]
-      expected: 'http://example.com/test?a=b&c=d'
-    },{
-      args: ['http', '1.2.3.4']
-      expected: 'http://1.2.3.4'
-    },{
-      args: ['http', '1:2::3:4']
-      expected: 'http://[1:2::3:4]'
-    },{
-      args: ['http', 'bog][us']
-      expected: 'http://bog%5D%5Bus'
-    },{
-      args: ['http', 'bog:u]s']
-      expected: 'http://bog%3Au%5Ds'
-    }]
-  announce 'testBuildUrl'
-  for test in TESTS
-    actual = buildUrl.apply undefined, test.args
-    if actual == test.expected
-      pass test.args
-    else
-      fail test.args, test.expected, actual
-
-###
-This test only checks that things work for strings formatted like
-document.cookie. Browsers maintain several properties about this string, for
-example cookie names are unique with no trailing whitespace.  See
-http://www.ietf.org/rfc/rfc2965.txt for the grammar.
-###
-testParseCookieString = ->
-  TESTS = [{
-      cs: ''
-      expected: {}
-    },{
-      cs: 'a=b'
-      expected: { a: 'b' }
-    },{
-      cs: 'a=b=c'
-      expected: { a: 'b=c' }
-    },{
-      cs: 'a=b; c=d'
-      expected: { a: 'b', c: 'd' }
-    },{
-      cs: 'a=b ; c=d'
-      expected: { a: 'b', c: 'd' }
-    },{
-      cs: 'a= b',
-      expected: { a: 'b' }
-    },{
-      cs: 'a='
-      expected: { a: '' }
-    }, {
-      cs: 'key',
-      expected: null
-    }, {
-      cs: 'key=%26%20'
-      expected: { key: '& ' }
-    }, {
-      cs: 'a=\'\''
-      expected: { a: '\'\'' }
-    }]
-  announce 'testParseCookieString'
-  for test in TESTS
-    actual = Parse.cookie test.cs
-    if JSON.stringify(actual) == JSON.stringify(test.expected)
-      pass test.cs
-    else
-      fail test.cs, test.expected, actual
-
-testParseQueryString = ->
-  TESTS = [{
-      qs: ''
-      expected: {}
-    },{
-      qs: 'a=b'
-      expected: { a: 'b' }
-    },{
-      qs: 'a=b=c'
-      expected: { a: 'b=c' }
-    },{
-      qs: 'a=b&c=d'
-      expected: { a: 'b', c: 'd' }
-    },{
-      qs: 'client=&relay=1.2.3.4%3A9001'
-      expected: { client: '', relay: '1.2.3.4:9001' }
-    },{
-      qs: 'a=b%26c=d'
-      expected: { a: 'b&c=d' }
-    },{
-      qs: 'a%3db=d'
-      expected: { 'a=b': 'd' }
-    },{
-      qs: 'a=b+c%20d'
-      expected: { 'a': 'b c d' }
-    },{
-      qs: 'a=b+c%2bd'
-      expected: { 'a': 'b c+d' }
-    },{
-      qs: 'a+b=c'
-      expected: { 'a b': 'c' }
-    },{
-      qs: 'a=b+c+d'
-      expected: { a: 'b c d' }
-    # First appearance wins.
-    },{
-      qs: 'a=b&c=d&a=e'
-      expected: { a: 'b', c: 'd' }
-    },{
-      qs: 'a'
-      expected: { a: '' }
-    },{
-      qs: '=b',
-      expected: { '': 'b' }
-    },{
-      qs: '&a=b'
-      expected: { '': '', a: 'b' }
-    },{
-      qs: 'a=b&'
-      expected: { a: 'b', '':'' }
-    },{
-      qs: 'a=b&&c=d'
-      expected: { a: 'b', '':'', c: 'd' }
-    }]
-  announce 'testParseQueryString'
-  for test in TESTS
-    actual = Query.parse test.qs
-    if JSON.stringify(actual) == JSON.stringify(test.expected)
-      pass test.qs
-    else
-      fail test.qs, test.expected, actual
-
-testGetParamBoolean = ->
-  TESTS = [{
-      qs: 'param=true'
-      expected: true
-    },{
-      qs: 'param',
-      expected: true
-    },{
-      qs: 'param='
-      expected: true
-    },{
-      qs: 'param=1'
-      expected: true
-    },{
-      qs: 'param=0'
-      expected: false
-    },{
-      qs: 'param=false'
-      expected: false
-    },{
-      qs: 'param=unexpected'
-      expected: null
-    },{
-      qs: 'pram=true'
-      expected: false
-    }]
-  announce 'testGetParamBoolean'
-  for test in TESTS
-    query = Query.parse test.qs
-    actual = Params.getBool(query, 'param', false)
-    if actual == test.expected
-      pass test.qs
-    else
-      fail test.qs, test.expected, actual
-
-testParseAddress = ->
-  TESTS = [{
-      spec: ''
-      expected: null
-    },{
-      spec: '3.3.3.3:4444'
-      expected: { host: '3.3.3.3', port: 4444 }
-    },{
-      spec: '3.3.3.3'
-      expected: null
-    },{
-      spec: '3.3.3.3:0x1111'
-      expected: null
-    },{
-      spec: '3.3.3.3:-4444'
-      expected: null
-    },{
-      spec: '3.3.3.3:65536'
-      expected: null
-    },{
-      spec: '[1:2::a:f]:4444'
-      expected: { host: '1:2::a:f', port: 4444 }
-    },{
-      spec: '[1:2::a:f]'
-      expected: null
-    },{
-      spec: '[1:2::a:f]:0x1111'
-      expected: null
-    },{
-      spec: '[1:2::a:f]:-4444'
-      expected: null
-    },{
-      spec: '[1:2::a:f]:65536'
-      expected: null
-    },{
-      spec: '[1:2::ffff:1.2.3.4]:4444'
-      expected: { host: '1:2::ffff:1.2.3.4', port: 4444 }
-    }]
-  announce 'testParseAddrSpec'
-  for test in TESTS
-    actual = Parse.address test.spec
-    if JSON.stringify(actual) == JSON.stringify(test.expected)
-      pass test.spec
-    else
-      fail test.spec, test.expected, actual
-
-testGetParamAddress = ->
-  DEFAULT = { host: '1.1.1.1', port: 2222 }
-  TESTS = [{
-      query: {}
-      expected: DEFAULT
-    },{
-      query: { addr: '3.3.3.3:4444' },
-      expected: { host: '3.3.3.3', port: 4444 }
-    },{
-      query: { x: '3.3.3.3:4444' }
-      expected: DEFAULT
-    },{
-      query: { addr: '---' }
-      expected: null
-    }]
-
-  announce 'testGetParamAddress'
-  for test in TESTS
-    actual = Params.getAddress test.query, 'addr', DEFAULT
-    if JSON.stringify(actual) == JSON.stringify(test.expected)
-      pass test.query
-    else
-      fail test.query, test.expected, actual
-
-testProxyPair = ->
-  announce 'testProxyPair'
-  fakeRelay = Parse.address '0.0.0.0:12345'
-  rateLimit = new DummyRateLimit()
-  destination = []
-  fakeClient =
-    send: (d) -> destination.push d
-  pp = new ProxyPair(fakeClient, fakeRelay, rateLimit)
-  pp.connectRelay()
-  if null != pp.relay.onopen then pass 'relay.onopen'
-  else fail 'relay onopen must not be null.'
-  if null != pp.relay.onclose then pass 'relay.onclose'
-  else fail 'relay onclose must not be null.'
-  if null != pp.relay.onerror then pass 'relay.onerror'
-  else fail 'relay onerror must not be null.'
-  if null != pp.relay.onmessage then pass 'relay.onmessage'
-  else fail 'relay onmessage must not be null.'
-  # TODO: Test for flush
-  # pp.c2rSchedule.push { data: 'omg' }
-  # pp.flush()
-  # if destination == ['omg'] then pass 'flush'
-  # else fail 'flush', ['omg'], destination
-
-testBuildUrl()
-testParseCookieString()
-testParseQueryString()
-testGetParamBoolean()
-testParseAddress()
-testGetParamAddress()
-testProxyPair()
diff --git a/proxy/spec.coffee b/proxy/spec.coffee
new file mode 100644
index 0000000..3d8ae61
--- /dev/null
+++ b/proxy/spec.coffee
@@ -0,0 +1,180 @@
+###
+jasmine tests for Snowflake
+###
+
+# Stubs to fake browser functionality.
+class WebSocket
+  OPEN: 1
+  CLOSED: 0
+ui = {}
+
+describe 'BuildUrl', ->
+  it 'should parse just protocol and host', ->
+    expect(buildUrl('http', 'example.com')).toBe 'http://example.com'
+  it 'should handle different ports', ->
+    expect buildUrl 'http', 'example.com', 80
+      .toBe 'http://example.com'
+    expect buildUrl 'http', 'example.com', 81
+      .toBe 'http://example.com:81'
+    expect buildUrl 'http', 'example.com', 443
+      .toBe 'http://example.com:443'
+    expect buildUrl 'http', 'example.com', 444
+      .toBe 'http://example.com:444'
+  it 'should handle paths', ->
+    expect buildUrl 'http', 'example.com', 80, '/'
+      .toBe 'http://example.com/'
+    expect buildUrl 'http', 'example.com', 80,'/test?k=%#v'
+      .toBe 'http://example.com/test%3Fk%3D%25%23v'
+    expect buildUrl 'http', 'example.com', 80, '/test'
+      .toBe 'http://example.com/test'
+  it 'should handle params', ->
+    expect buildUrl 'http', 'example.com', 80, '/test', [['k', '%#v']]
+      .toBe 'http://example.com/test?k=%25%23v'
+    expect buildUrl 'http', 'example.com', 80, '/test', [['a', 'b'], ['c', 'd']]
+      .toBe 'http://example.com/test?a=b&c=d'
+  it 'should handle ips', ->
+    expect buildUrl 'http', '1.2.3.4'
+      .toBe 'http://1.2.3.4'
+    expect buildUrl 'http', '1:2::3:4'
+      .toBe 'http://[1:2::3:4]'
+  it 'should handle bogus', ->
+    expect buildUrl 'http', 'bog][us'
+      .toBe 'http://bog%5D%5Bus'
+    expect buildUrl 'http', 'bog:u]s'
+      .toBe 'http://bog%3Au%5Ds'
+
+describe 'Parse', ->
+
+  describe 'cookie', ->
+    it 'parses correctly', ->
+      expect Parse.cookie ''
+        .toEqual {}
+      expect Parse.cookie 'a=b'
+        .toEqual { a: 'b' }
+      expect Parse.cookie 'a=b=c'
+        .toEqual { a: 'b=c' }
+      expect Parse.cookie 'a=b; c=d'
+        .toEqual { a: 'b', c: 'd' }
+      expect Parse.cookie 'a=b ; c=d'
+        .toEqual { a: 'b', c: 'd' }
+      expect Parse.cookie 'a= b'
+        .toEqual { a: 'b' }
+      expect Parse.cookie 'a='
+        .toEqual { a: '' }
+      expect Parse.cookie 'key'
+        .toBeNull()
+      expect Parse.cookie 'key=%26%20'
+        .toEqual { key: '& ' }
+      expect Parse.cookie 'a=\'\''
+        .toEqual { a: '\'\'' }
+
+  describe 'address', ->
+    it 'parses IPv4', ->
+      expect Parse.address ''
+        .toBeNull()
+      expect Parse.address '3.3.3.3:4444'
+        .toEqual { host: '3.3.3.3', port: 4444 }
+      expect Parse.address '3.3.3.3'
+        .toBeNull()
+      expect Parse.address '3.3.3.3:0x1111'
+        .toBeNull()
+      expect Parse.address '3.3.3.3:-4444'
+        .toBeNull()
+      expect Parse.address '3.3.3.3:65536'
+        .toBeNull()
+    it 'parses IPv6', ->
+      expect Parse.address '[1:2::a:f]:4444'
+        .toEqual { host: '1:2::a:f', port: 4444 }
+      expect Parse.address '[1:2::a:f]'
+        .toBeNull()
+      expect Parse.address '[1:2::a:f]:0x1111'
+        .toBeNull()
+      expect Parse.address '[1:2::a:f]:-4444'
+        .toBeNull()
+      expect Parse.address '[1:2::a:f]:65536'
+        .toBeNull()
+      expect Parse.address '[1:2::ffff:1.2.3.4]:4444'
+        .toEqual { host: '1:2::ffff:1.2.3.4', port: 4444 }
+
+describe 'query string', ->
+  it 'should parse correctly', ->
+    expect Query.parse ''
+      .toEqual {}
+    expect Query.parse 'a=b'
+      .toEqual { a: 'b' }
+    expect Query.parse 'a=b=c'
+      .toEqual { a: 'b=c' }
+    expect Query.parse 'a=b&c=d'
+      .toEqual { a: 'b', c: 'd' }
+    expect Query.parse 'client=&relay=1.2.3.4%3A9001'
+      .toEqual { client: '', relay: '1.2.3.4:9001' }
+    expect Query.parse 'a=b%26c=d'
+      .toEqual { a: 'b&c=d' }
+    expect Query.parse 'a%3db=d'
+      .toEqual { 'a=b': 'd' }
+    expect Query.parse 'a=b+c%20d'
+      .toEqual { 'a': 'b c d' }
+    expect Query.parse 'a=b+c%2bd'
+      .toEqual { 'a': 'b c+d' }
+    expect Query.parse 'a+b=c'
+      .toEqual { 'a b': 'c' }
+    expect Query.parse 'a=b+c+d'
+      .toEqual { a: 'b c d' }
+  it 'uses the first appearance of duplicate key', ->
+    expect Query.parse 'a=b&c=d&a=e'
+      .toEqual { a: 'b', c: 'd' }
+    expect Query.parse 'a'
+      .toEqual { a: '' }
+    expect Query.parse '=b'
+      .toEqual { '': 'b' }
+    expect Query.parse '&a=b'
+      .toEqual { '': '', a: 'b' }
+    expect Query.parse 'a=b&'
+      .toEqual { a: 'b', '':'' }
+    expect Query.parse 'a=b&&c=d'
+      .toEqual { a: 'b', '':'', c: 'd' }
+
+describe 'Params', ->
+  describe 'bool', ->
+    getBool = (query) ->
+      Params.getBool (Query.parse query), 'param', false
+    it 'parses correctly', ->
+      expect(getBool 'param=true').toEqual true
+      expect(getBool 'param').toEqual true
+      expect(getBool 'param=').toEqual true
+      expect(getBool 'param=1').toEqual true
+      expect(getBool 'param=0').toEqual false
+      expect(getBool 'param=false').toEqual false
+      expect(getBool 'param=unexpected').toBeNull()
+      expect(getBool 'pram=true').toEqual false
+
+  describe 'address', ->
+    DEFAULT = { host: '1.1.1.1', port: 2222 }
+    getAddress = (query) ->
+      Params.getAddress query, 'addr', DEFAULT
+    it 'parses correctly', ->
+      expect(getAddress {}).toEqual DEFAULT
+      expect getAddress { addr: '3.3.3.3:4444' }
+        .toEqual { host: '3.3.3.3', port: 4444 }
+      expect getAddress { x: '3.3.3.3:4444' }
+        .toEqual DEFAULT
+      expect getAddress { addr: '---' }
+        .toBeNull()
+
+describe 'ProxyPair', ->
+  fakeRelay = Parse.address '0.0.0.0:12345'
+  rateLimit = new DummyRateLimit()
+  destination = []
+  fakeClient = send: (d) -> destination.push d
+  pp = new ProxyPair(fakeClient, fakeRelay, rateLimit)
+  it 'handles relay correctly', ->
+    pp.connectRelay()
+    expect(pp.relay.onopen).not.toBeNull()
+    expect(pp.relay.onclose).not.toBeNull()
+    expect(pp.relay.onerror).not.toBeNull()
+    expect(pp.relay.onmessage).not.toBeNull()
+  # TODO: Test for flush
+  # pp.c2rSchedule.push { data: 'omg' }
+  # pp.flush()
+  # if destination == ['omg'] then pass 'flush'
+  # else fail 'flush', ['omg'], destination
diff --git a/proxy/websocket.coffee b/proxy/websocket.coffee
index eca6f2a..03fa0e8 100644
--- a/proxy/websocket.coffee
+++ b/proxy/websocket.coffee
@@ -57,3 +57,4 @@ makeWebsocket = (addr) ->
   ws.binaryType = 'arraybuffer'
   ws
 
+# module.exports.buildUrl = buildUrl





More information about the tor-commits mailing list