From a2db8ab2d79789c4b7cff4616069ffe224c15036 Mon Sep 17 00:00:00 2001 From: Jim Cowart Date: Sat, 2 Mar 2013 16:32:57 -0500 Subject: [PATCH] Added tests for Bindings resolver to specifically target failing conditions. Now to fix those failures.... --- build.json | 5 +- lib/postal.js | 2 +- lib/postal.min.js | 2 +- spec/AmqpBindingsResolver.spec.js | 510 ++++++++++++++++++++++++++---- spec/index.html | 6 +- src/AmqpBindingsResolver.js | 2 +- 6 files changed, 455 insertions(+), 72 deletions(-) diff --git a/build.json b/build.json index 4ded4b4..9bd38f0 100644 --- a/build.json +++ b/build.json @@ -5,14 +5,11 @@ "/": "./" } }, - "anvil.jshint" : { - "all": true - }, "output": { "full": "lib", "partial": { "**/lib/postal.*" : [ "example/standard/js", "example/amd/js/libs/postal" ] } }, - "dependencies": [ "anvil.http", "anvil.uglify", "anvil.jshint" ] + "dependencies": [ "anvil.uglify" ] } \ No newline at end of file diff --git a/lib/postal.js b/lib/postal.js index fa5d5a1..ca693df 100644 --- a/lib/postal.js +++ b/lib/postal.js @@ -212,7 +212,7 @@ var pattern = ("^" + binding.replace( /\./g, "\\." ) // escape actual periods .replace( /\*/g, "[A-Z,a-z,0-9]*" ) // asterisks match any alpha-numeric 'word' .replace( /#/g, ".*" ) + "$") // hash matches 'n' # of words (+ optional on start/end of topic) - .replace( "\\..*$", "(\\..*)*$" ) // fix end of topic matching on hash wildcards + .replace( "\\..*$", "(\\..*)*$" ) // fix end of topic matching on hash wildcards .replace( "^.*\\.", "^(.*\\.)*" ); // fix beginning of topic matching on hash wildcards var rgx = new RegExp( pattern ); var result = rgx.test( topic ); diff --git a/lib/postal.min.js b/lib/postal.min.js index 7d6bb4e..5faae17 100644 --- a/lib/postal.min.js +++ b/lib/postal.min.js @@ -4,4 +4,4 @@ License: Dual licensed MIT (http://www.opensource.org/licenses/mit-license) & GPL (http://www.opensource.org/licenses/gpl-license) Version 0.8.2 */ -(function(e,t){typeof module=="object"&&module.exports?module.exports=function(e){return e=e||require("underscore"),t(e)}:typeof define=="function"&&define.amd?define(["underscore"],function(n){return t(n,e)}):e.postal=t(e._,e)})(this,function(e,t,n){var r="/",i=0,s="postal",o=function(){var t;return function(n){var r=!1;return e.isString(n)?(r=n===t,t=n):(r=e.isEqual(n,t),t=e.clone(n)),!r}},u=function(){var t=[];return function(n){var r=!e.any(t,function(t){return e.isObject(n)||e.isArray(n)?e.isEqual(n,t):n===t});return r&&t.push(n),r}},a=function(e){this.channel=e||r};a.prototype.subscribe=function(){return arguments.length===1?new f(this.channel,arguments[0].topic,arguments[0].callback):new f(this.channel,arguments[0],arguments[1])},a.prototype.publish=function(){var e=arguments.length===1?Object.prototype.toString.call(arguments[0])==="[object String]"?{topic:arguments[0]}:arguments[0]:{topic:arguments[0],data:arguments[1]};return e.channel=this.channel,p.configuration.bus.publish(e)};var f=function(e,t,n){this.channel=e,this.topic=t,this.callback=n,this.constraints=[],this.context=null,p.configuration.bus.publish({channel:s,topic:"subscription.created",data:{event:"subscription.created",channel:e,topic:t}}),p.configuration.bus.subscribe(this)};f.prototype={unsubscribe:function(){p.configuration.bus.unsubscribe(this),p.configuration.bus.publish({channel:s,topic:"subscription.removed",data:{event:"subscription.removed",channel:this.channel,topic:this.topic}})},defer:function(){var e=this.callback;return this.callback=function(t){setTimeout(e,0,t)},this},disposeAfter:function(t){if(e.isNaN(t)||t<=0)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var n=this.callback,r=e.after(t,e.bind(function(){this.unsubscribe()},this));return this.callback=function(){n.apply(this.context,arguments),r()},this},distinctUntilChanged:function(){return this.withConstraint(new o),this},distinct:function(){return this.withConstraint(new u),this},once:function(){this.disposeAfter(1)},withConstraint:function(t){if(!e.isFunction(t))throw"Predicate constraint must be a function";return this.constraints.push(t),this},withConstraints:function(t){var n=this;return e.isArray(t)&&e.each(t,function(e){n.withConstraint(e)}),n},withContext:function(e){return this.context=e,this},withDebounce:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.debounce(n,t),this},withDelay:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=function(e){setTimeout(function(){n(e)},t)},this},withThrottle:function(t){if(e.isNaN(t))throw"Milliseconds must be a number";var n=this.callback;return this.callback=e.throttle(n,t),this},subscribe:function(e){return this.callback=e,this}};var l={cache:{},compare:function(e,t){if(this.cache[t]&&this.cache[t][e])return!0;var n=("^"+e.replace(/\./g,"\\.").replace(/\*/g,"[A-Z,a-z,0-9]*").replace(/#/g,".*")+"$").replace("\\..*$","(\\..*)*$").replace("^.*\\.","^(.*\\.)*"),r=new RegExp(n),i=r.test(t);return i&&(this.cache[t]||(this.cache[t]={}),this.cache[t][e]=!0),i},reset:function(){this.cache={}}},c=function(t,n){p.configuration.resolver.compare(t.topic,n.topic)&&e.all(t.constraints,function(e){return e.call(t.context,n.data,n)})&&typeof t.callback=="function"&&t.callback.call(t.context,n.data,n)},h={addWireTap:function(e){var t=this;return t.wireTaps.push(e),function(){var n=t.wireTaps.indexOf(e);n!==-1&&t.wireTaps.splice(n,1)}},publish:function(t){return t.timeStamp=new Date,e.each(this.wireTaps,function(e){e(t.data,t)}),this.subscriptions[t.channel]&&e.each(this.subscriptions[t.channel],function(e){var n=0,r=e.length,i;while(n=n)throw"The value provided to disposeAfter (maxCalls) must be a number greater than zero.";var i=this.callback,s=t.after(n,t.bind(function(){this.unsubscribe()},this));return this.callback=function(){i.apply(this.context,arguments),s()},this},distinctUntilChanged:function(){return this.withConstraint(new s),this},distinct:function(){return this.withConstraint(new c),this},once:function(){this.disposeAfter(1)},withConstraint:function(n){if(!t.isFunction(n))throw"Predicate constraint must be a function";return this.constraints.push(n),this},withConstraints:function(n){var i=this;return t.isArray(n)&&t.each(n,function(t){i.withConstraint(t)}),i},withContext:function(t){return this.context=t,this},withDebounce:function(n){if(t.isNaN(n))throw"Milliseconds must be a number";var i=this.callback;return this.callback=t.debounce(i,n),this},withDelay:function(n){if(t.isNaN(n))throw"Milliseconds must be a number";var i=this.callback;return this.callback=function(t){setTimeout(function(){i(t)},n)},this},withThrottle:function(n){if(t.isNaN(n))throw"Milliseconds must be a number";var i=this.callback;return this.callback=t.throttle(i,n),this},subscribe:function(t){return this.callback=t,this}};var a={cache:{},compare:function(t,n){if(this.cache[n]&&this.cache[n][t])return!0;var i=("^"+t.replace(/\./g,"\\.").replace(/\*/g,"[A-Z,a-z,0-9]*").replace(/#/g,".*")+"$").replace("\\..*$","(\\..*)*$").replace("^.*\\.","^(.*\\.)*"),s=RegExp(i),c=s.test(n);return c&&(this.cache[n]||(this.cache[n]={}),this.cache[n][t]=!0),c},reset:function(){this.cache={}}},o=function(n,i){h.configuration.resolver.compare(n.topic,i.topic)&&t.all(n.constraints,function(t){return t.call(n.context,i.data,i)})&&"function"==typeof n.callback&&n.callback.call(n.context,i.data,i)},u={addWireTap:function(t){var n=this;return n.wireTaps.push(t),function(){var i=n.wireTaps.indexOf(t);-1!==i&&n.wireTaps.splice(i,1)}},publish:function(n){return n.timeStamp=new Date,t.each(this.wireTaps,function(t){t(n.data,n)}),this.subscriptions[n.channel]&&t.each(this.subscriptions[n.channel],function(t){for(var i,s=0,c=t.length;c>s;)(i=t[s++])&&o(i,n)}),n},reset:function(){this.subscriptions&&(t.each(this.subscriptions,function(n){t.each(n,function(t){for(;t.length;)t.pop().unsubscribe()})}),this.subscriptions={})},subscribe:function(t){var n,i=this.subscriptions[t.channel];return i||(i=this.subscriptions[t.channel]={}),n=this.subscriptions[t.channel][t.topic],n||(n=this.subscriptions[t.channel][t.topic]=[]),n.push(t),t},subscriptions:{},wireTaps:[],unsubscribe:function(t){if(this.subscriptions[t.channel][t.topic])for(var n=this.subscriptions[t.channel][t.topic].length,i=0;n>i;i++)if(this.subscriptions[t.channel][t.topic][i]===t){this.subscriptions[t.channel][t.topic].splice(i,1);break}}};u.subscriptions[i]={};var h={configuration:{bus:u,resolver:a,DEFAULT_CHANNEL:n,SYSTEM_CHANNEL:i},ChannelDefinition:e,SubscriptionDefinition:r,channel:function(t){return new e(t)},subscribe:function(t){return new r(t.channel||n,t.topic,t.callback)},publish:function(t){return t.channel=t.channel||n,h.configuration.bus.publish(t)},addWireTap:function(t){return this.configuration.bus.addWireTap(t)},linkChannels:function(i,s){var c=[];return i=t.isArray(i)?i:[i],s=t.isArray(s)?s:[s],t.each(i,function(i){i.topic||"#",t.each(s,function(s){var e=s.channel||n;c.push(h.subscribe({channel:i.channel||n,topic:i.topic||"#",callback:function(n,i){var c=t.clone(i);c.topic=t.isFunction(s.topic)?s.topic(i.topic):s.topic||i.topic,c.channel=e,c.data=n,h.publish(c)}}))})}),c},utils:{getSubscribersFor:function(){var t=arguments[0],n=arguments[1];return 1===arguments.length&&(t=arguments[0].channel||h.configuration.DEFAULT_CHANNEL,n=arguments[0].topic),h.configuration.bus.subscriptions[t]&&h.configuration.bus.subscriptions[t].hasOwnProperty(n)?h.configuration.bus.subscriptions[t][n]:[]},reset:function(){h.configuration.bus.reset(),h.configuration.resolver.reset()}}};return h}); \ No newline at end of file diff --git a/spec/AmqpBindingsResolver.spec.js b/spec/AmqpBindingsResolver.spec.js index f23405d..4b74280 100644 --- a/spec/AmqpBindingsResolver.spec.js +++ b/spec/AmqpBindingsResolver.spec.js @@ -1,75 +1,459 @@ - describe( "amqpBindingsResolver", function () { describe( "When calling compare", function () { - describe( "With topic Top.Middle.Bottom and binding Top.Middle.Bottom", function () { - var result = bindingsResolver.compare( "Top.Middle.Bottom", "Top.Middle.Bottom" ), - cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.Middle.Bottom"]; - it( "Result should be true", function () { - expect( result ).to.be.ok(); + beforeEach(function(){ + bindingsResolver.reset(); + }); + describe("With '*' wildcards", function(){ + // Passing matches + describe( "With topic Top.Middle.Bottom and binding *.Middle.Bottom", function () { + var result = bindingsResolver.compare( "*.Middle.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["*.Middle.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - it( "Should create a resolver cache entry", function () { - expect( cached ).to.be.ok(); + describe( "With topic Top.Middle.Bottom and binding Top.*.Bottom", function () { + var result = bindingsResolver.compare( "Top.*.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.*.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - } ); - describe( "With topic Top.Middle.Bottom and binding Top.#.Bottom", function () { - var result = bindingsResolver.compare( "Top.#.Bottom", "Top.Middle.Bottom" ), - cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.#.Bottom"]; - it( "Result should be true", function () { - expect( result ).to.be.ok(); + describe( "With topic Top.Middle.Bottom and binding Top.Middle.*", function () { + var result = bindingsResolver.compare( "Top.Middle.*", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.Middle.*"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - it( "Should create a resolver cache entry", function () { - expect( cached ).to.be.ok(); + describe( "With topic Top.Middle.Bottom and binding Top.*.*", function () { + var result = bindingsResolver.compare( "Top.*.*", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.*.*"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - } ); - describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.#.Bottom", function () { - var result = bindingsResolver.compare( "Top.#.Bottom", "Top.Middle.SubMiddle.Bottom" ), - cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.#.Bottom"]; - it( "Result should be true", function () { - expect( result ).to.be.ok(); - } ); - it( "Should create a resolver cache entry", function () { - expect( cached ).to.be.ok(); - } ); - } ); - describe( "With topic Top.SubTop.Middle.SubMiddle.Bottom and binding Top.#.Bottom", function () { - var result = bindingsResolver.compare( "Top.#.Bottom", "Top.SubTop.Middle.SubMiddle.Bottom" ), - cached = bindingsResolver.cache["Top.SubTop.Middle.SubMiddle.Bottom"]["Top.#.Bottom"]; - it( "Result should be true", function () { - expect( result ).to.be.ok(); - } ); - it( "Should create a resolver cache entry", function () { - expect( cached ).to.be.ok(); - } ); - } ); - describe( "With topic Top.Middle.Bottom and binding Top.*.Bottom", function () { - var result = bindingsResolver.compare( "Top.*.Bottom", "Top.Middle.Bottom" ), - cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.*.Bottom"]; - it( "Result should be true", function () { - expect( result ).to.be.ok(); + describe( "With topic Top.Middle.Bottom and binding Top.*.*", function () { + var result = bindingsResolver.compare( "*.*.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["*.*.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - it( "Should create a resolver cache entry", function () { - expect( cached ).to.be.ok(); + describe( "With topic Top.Middle.Bottom and binding *.Middle.*", function () { + var result = bindingsResolver.compare( "*.Middle.*", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["*.Middle.*"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - } ); - describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.*.Bottom", function () { - var result = bindingsResolver.compare( "Top.*.Bottom", "Top.Middle.SubMiddle.Bottom" ), - cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.*.Bottom"]; - it( "Result should be false", function () { - expect( result ).to.not.be.ok() - } ); - it( "Should *not* create a resolver cache entry", function () { - expect( cached ).to.not.be.ok() - } ); - } ); - describe( "With topic Top.Middle.Bottom and binding #.*.Bottom", function () { - var result = bindingsResolver.compare( "#.*.Bottom", "Top.Middle.Bottom" ), - cached = bindingsResolver.cache["Top.Middle.Bottom"]["#.*.Bottom"]; - it( "Result should be true", function () { - expect( result ).to.be.ok(); + describe( "With topic Top.Middle.Bottom and binding *.*.*", function () { + var result = bindingsResolver.compare( "*.*.*", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["*.*.*"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); } ); - it( "Should create a resolver cache entry", function () { - expect( cached ).to.be.ok(); + + // Failing Matches + describe( "With topic Top.Middle.SubMiddle.Bottom and binding *.Middle.Bottom", function () { + var result = bindingsResolver.compare( "*.Middle.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["*.Middle.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok() + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok() + } ); } ); - } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.*.Bottom", function () { + var result = bindingsResolver.compare( "Top.*.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.*.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok() + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok() + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.Middle.*", function () { + var result = bindingsResolver.compare( "Top.Middle.*", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.Middle.*"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.*.*", function () { + var result = bindingsResolver.compare( "Top.*.*", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.*.*"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.*.*", function () { + var result = bindingsResolver.compare( "*.*.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["*.*.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding *.Middle.*", function () { + var result = bindingsResolver.compare( "*.Middle.*", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["*.Middle.*"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding *.*.*", function () { + var result = bindingsResolver.compare( "*.*.*", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["*.*.*"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + + }); + describe("With '#' wildcards", function(){ + // Passing matches + // # at beginning of binding + describe( "With topic Top.Middle.Bottom and binding #.Middle.Bottom", function () { + var result = bindingsResolver.compare( "#.Middle.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["#.Middle.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.SubTop.Middle.Bottom and binding #.Middle.Bottom", function () { + var result = bindingsResolver.compare( "#.Middle.Bottom", "Top.SubTop.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.SubTop.Middle.Bottom"]["#.Middle.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Middle.Bottom and binding #.Middle.Bottom", function () { + var result = bindingsResolver.compare( "#.Middle.Bottom", "Middle.Bottom" ), + cached = bindingsResolver.cache["Middle.Bottom"]["#.Middle.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + // # in middle of binding + describe( "With topic Top.Middle.Bottom and binding Top.#.Bottom", function () { + var result = bindingsResolver.compare( "Top.#.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.#.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.#.Bottom", function () { + var result = bindingsResolver.compare( "Top.#.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.#.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.SubTop.Middle.SubMiddle.Bottom and binding Top.#.Bottom", function () { + var result = bindingsResolver.compare( "Top.#.Bottom", "Top.SubTop.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.SubTop.Middle.SubMiddle.Bottom"]["Top.#.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.Bottom and binding Top.#.Bottom", function () { + var result = bindingsResolver.compare( "Top.#.Bottom", "Top.Bottom" ), + cached = bindingsResolver.cache["Top.Bottom"] && bindingsResolver.cache["Top.Bottom"]["Top.#.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + // # at end of binding + describe( "With topic Top.Middle.Bottom and binding Top.Middle.#", function () { + var result = bindingsResolver.compare( "Top.Middle.#", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.Middle.#"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.SubTop.Middle.Bottom and binding Top.SubTop.#", function () { + var result = bindingsResolver.compare( "Top.SubTop.#", "Top.SubTop.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.SubTop.Middle.Bottom"]["Top.SubTop.#"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Middle.Bottom and binding Middle.#", function () { + var result = bindingsResolver.compare( "Middle.#", "Middle.Bottom" ), + cached = bindingsResolver.cache["Middle.Bottom"]["Middle.#"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + // Failing matches + // # at beginning of binding + describe( "With topic Top.Middle.SubMiddle.Bottom and binding #.Middle.Bottom", function () { + var result = bindingsResolver.compare( "#.Middle.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["#.Middle.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.SubTop.Middle.SubMiddle.Bottom and binding #.Middle.Bottom", function () { + var result = bindingsResolver.compare( "#.Middle.Bottom", "Top.SubTop.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.SubTop.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.SubTop.Middle.SubMiddle.Bottom"]["#.Middle.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Middle.Bottom and binding #.Middle.SubMiddle.Bottom", function () { + var result = bindingsResolver.compare( "#.Middle.Bottom", "Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Middle.SubMiddle.Bottom"]["#.Middle.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + // # in middle of binding + describe( "With topic Top.Middle.Bottom and binding Top.SubTop.#.Bottom", function () { + var result = bindingsResolver.compare( "Top.SubTop.#.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"] && bindingsResolver.cache["Top.Middle.Bottom"]["Top.SubTop.#.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom.SubBottom and binding Top.#.Bottom", function () { + var result = bindingsResolver.compare( "Top.#.Bottom", "Top.Middle.SubMiddle.Bottom.SubBottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom.SubBottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom.SubBottom"]["Top.#.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.SubTop.Middle.SubMiddle.Bottom and binding Top.#.Middle.Bottom", function () { + var result = bindingsResolver.compare( "Top.#.Middle.Bottom", "Top.SubTop.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.SubTop.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.SubTop.Middle.SubMiddle.Bottom"]["Top.#.Middle.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.SubTop.Bottom and binding SubTop.#.Bottom", function () { + var result = bindingsResolver.compare( "SubTop.#.Bottom", "Top.SubTop.Bottom" ), + cached = bindingsResolver.cache["Top.SubTop.Bottom"] && bindingsResolver.cache["Top.SubTop.Bottom"]["SubTop.#.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + // # at end of binding + describe( "With topic Top.Bottom and binding Top.Middle.#", function () { + var result = bindingsResolver.compare( "Top.Middle.#", "Top.Bottom" ), + cached = bindingsResolver.cache["Top.Bottom"] && bindingsResolver.cache["Top.Bottom"]["Top.Middle.#"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.Bottom and binding Top.SubTop.#", function () { + var result = bindingsResolver.compare( "Top.SubTop.#", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"] && bindingsResolver.cache["Top.Middle.Bottom"]["Top.SubTop.#"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Bottom and binding Middle.#", function () { + var result = bindingsResolver.compare( "Middle.#", "Bottom" ), + cached = bindingsResolver.cache["Bottom"] && bindingsResolver.cache["Bottom"]["Middle.#"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + }); + describe("With both '#' and '*' wildcards", function(){ + // Passing matches + describe( "With topic Top.Middle.Bottom and binding #.*.Bottom", function () { + var result = bindingsResolver.compare( "#.*.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["#.*.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding #.*.Bottom", function () { + var result = bindingsResolver.compare( "#.*.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["#.*.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.Bottom and binding #.*.Bottom", function () { + var result = bindingsResolver.compare( "#.*.Bottom", "Top.Bottom" ), + cached = bindingsResolver.cache["Top.Bottom"]["#.*.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic Top.Bottom and binding *.#.Bottom", function () { + var result = bindingsResolver.compare( "*.#.Bottom", "Top.Bottom" ), + cached = bindingsResolver.cache["Top.Bottom"] && bindingsResolver.cache["Top.Bottom"]["*.#.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + // Failing matches + describe( "With topic Bottom and binding #.*.Bottom", function () { + var result = bindingsResolver.compare( "#.*.Bottom", "Bottom" ), + cached = bindingsResolver.cache["Bottom"] && bindingsResolver.cache["Bottom"]["#.*.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Middle.SubMiddle.Bottom and binding Top.Middle.SubMiddle.#.*.Bottom", function () { + var result = bindingsResolver.compare( "Top.Middle.SubMiddle.#.*.Bottom", "Top.Middle.SubMiddle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"] && bindingsResolver.cache["Top.Middle.SubMiddle.Bottom"]["Top.Middle.SubMiddle.#.*.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + describe( "With topic Top.Bottom and binding #.*.Middle.Bottom", function () { + var result = bindingsResolver.compare( "#.*.Middle.Bottom", "Top.Bottom" ), + cached = bindingsResolver.cache["Top.Bottom"] && bindingsResolver.cache["Top.Bottom"]["#.*.Middle.Bottom"]; + it( "Result should be false", function () { + expect( result ).to.not.be.ok(); + } ); + it( "Should *not* create a resolver cache entry", function () { + expect( cached ).to.not.be.ok(); + } ); + } ); + }); + describe("With plain string matching", function() { + describe( "With topic Top.Middle.Bottom and binding Top.Middle.Bottom", function () { + var result = bindingsResolver.compare( "Top.Middle.Bottom", "Top.Middle.Bottom" ), + cached = bindingsResolver.cache["Top.Middle.Bottom"]["Top.Middle.Bottom"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + describe( "With topic 'Topic' and binding 'Topic'", function () { + var result = bindingsResolver.compare( "Topic", "Topic" ), + cached = bindingsResolver.cache["Topic"]["Topic"]; + it( "Result should be true", function () { + expect( result ).to.be.ok(); + } ); + it( "Should create a resolver cache entry", function () { + expect( cached ).to.be.ok(); + } ); + } ); + }); } ); } ); \ No newline at end of file diff --git a/spec/index.html b/spec/index.html index f94da4b..56485d6 100644 --- a/spec/index.html +++ b/spec/index.html @@ -23,13 +23,15 @@ + + diff --git a/src/AmqpBindingsResolver.js b/src/AmqpBindingsResolver.js index adeec4f..81506e6 100644 --- a/src/AmqpBindingsResolver.js +++ b/src/AmqpBindingsResolver.js @@ -8,7 +8,7 @@ var bindingsResolver = { var pattern = ("^" + binding.replace( /\./g, "\\." ) // escape actual periods .replace( /\*/g, "[A-Z,a-z,0-9]*" ) // asterisks match any alpha-numeric 'word' .replace( /#/g, ".*" ) + "$") // hash matches 'n' # of words (+ optional on start/end of topic) - .replace( "\\..*$", "(\\..*)*$" ) // fix end of topic matching on hash wildcards + .replace( "\\..*$", "(\\..*)*$" ) // fix end of topic matching on hash wildcards .replace( "^.*\\.", "^(.*\\.)*" ); // fix beginning of topic matching on hash wildcards var rgx = new RegExp( pattern ); var result = rgx.test( topic );