From 487dfe697a94b518da4cacb61678a109aeffb1e3 Mon Sep 17 00:00:00 2001 From: Serene Han Date: Wed, 13 Jan 2016 10:27:29 -0800 Subject: [PATCH] convert rest of address spec tests, ProxyPair test, and move parse functions into Parse container --- proxy/snowflake.coffee | 51 +++++++------ proxy/snowflake_test.coffee | 145 +++++++++++++++++++++++++++++++++--- 2 files changed, 164 insertions(+), 32 deletions(-) diff --git a/proxy/snowflake.coffee b/proxy/snowflake.coffee index fc30902..d040cbc 100644 --- a/proxy/snowflake.coffee +++ b/proxy/snowflake.coffee @@ -57,26 +57,11 @@ Query = encodeURIComponent(param[1]) parts.join '&' -Params = - getBool: (query, param, defaultValue) -> - val = query[param] - return defaultValue if undefined == val - return true if 'true' == val || '1' == val || '' == val - return false if 'false' == val || '0' == val - return null - - # Get an object value and parse it as a byte count. Example byte counts are - # "100" and "1.3m". Returns default_val if param is not a key. Return null on - # a parsing error. - getByteCount: (query, param, defaultValue) -> - spec = query[param] - return defaultValue if undefined == spec - parseByteCount spec - +Parse = # Parse a cookie data string (usually document.cookie). The return type is an # object mapping cookies names to values. Returns null on error. # http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038 - parseCookie: (cookies) -> + cookie: (cookies) -> result = {} strings = [] strings = cookies.split ';' if cookies @@ -90,7 +75,7 @@ Params = # Parse an address in the form 'host:port'. Returns an Object with keys 'host' # (String) and 'port' (int). Returns null on error. - parseAddress: (spec) -> + address: (spec) -> m = null # IPv6 syntax. m = spec.match(/^\[([\0-9a-fA-F:.]+)\]:([0-9]+)$/) if !m @@ -104,9 +89,9 @@ Params = return null { host: host, port: port } - # Parse a count of bytes. A suffix of "k", "m", or "g" (or uppercase) + # Parse a count of bytes. A suffix of 'k', 'm', or 'g' (or uppercase) # does what you would think. Returns null on error. - parseByteCount: (spec) -> + byteCount: (spec) -> UNITS = { k: 1024, m: 1024 * 1024, g: 1024 * 1024 * 1024 K: 1024, M: 1024 * 1024, G: 1024 * 1024 * 1024 @@ -122,6 +107,30 @@ Params = return null if null == units count * Number(units) +Params = + getBool: (query, param, defaultValue) -> + val = query[param] + return defaultValue if undefined == val + return true if 'true' == val || '1' == val || '' == val + return false if 'false' == val || '0' == val + return null + + # Get an object value and parse it as a byte count. Example byte counts are + # '100' and '1.3m'. Returns |defaultValue| if param is not a key. Return null on + # a parsing error. + getByteCount: (query, param, defaultValue) -> + spec = query[param] + return defaultValue if undefined == spec + Parse.byteCount spec + + # Get an object value and parse it as an address spec. Returns |defaultValue| + # if param is not a key. Returns null on a parsing error. + getAddress: (query, param, defaultValue) -> + val = query[param] + return defaultValue if undefined == val + Parse.address val + + safe_repr = (s) -> SAFE_LOGGING ? '[scrubbed]' : JSON.stringify(s) # HEADLESS is true if we are running not in a browser with a DOM. @@ -286,7 +295,7 @@ class Snowflake # TODO: User-supplied for now, but should fetch from facilitator later. setRelayAddr: (relayAddr) -> - addr = Params.parseAddress relayAddr + addr = Parse.address relayAddr if !addr log 'Invalid address spec.' return false diff --git a/proxy/snowflake_test.coffee b/proxy/snowflake_test.coffee index 9f5a244..6ca151b 100644 --- a/proxy/snowflake_test.coffee +++ b/proxy/snowflake_test.coffee @@ -1,5 +1,3 @@ -# s = require './snowflake' - window = {} VERBOSE = false @@ -24,6 +22,10 @@ fail = (test, expected, actual) -> ' expected: ' + JSON.stringify(expected) + ' actual: ' + JSON.stringify(actual) +# Stubs for browser functionality. +class WebSocket + OPEN: 1 + CLOSED: 0 testBuildUrl = -> TESTS = [{ @@ -69,7 +71,6 @@ testBuildUrl = -> args: ['http', 'bog:u]s'] expected: 'http://bog%3Au%5Ds' }] - announce 'testBuildUrl' for test in TESTS actual = buildUrl.apply undefined, test.args @@ -116,10 +117,9 @@ testParseCookieString = -> cs: 'a=\'\'' expected: { a: '\'\'' } }] - announce 'testParseCookieString' for test in TESTS - actual = Params.parseCookie test.cs + actual = Parse.cookie test.cs if JSON.stringify(actual) == JSON.stringify(test.expected) pass test.cs else @@ -179,7 +179,6 @@ testParseQueryString = -> qs: 'a=b&&c=d' expected: { a: 'b', '':'', c: 'd' } }] - announce 'testParseQueryString' for test in TESTS actual = Query.parse test.qs @@ -188,14 +187,138 @@ testParseQueryString = -> 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' - addr = Params.parseAddress '0.0.0.0:35302' - console.log addr - pair = new ProxyPair(null, addr, 0) - pair.connectRelay() + 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() -# testProxyPair() +testGetParamBoolean() +testParseAddress() +testGetParamAddress() +testProxyPair()