woadwarrior / bloom

Simple sha256 hash based counting bloom filter implementations in Python and Javascript. Filters built with the python module can be serialized to JSON and loaded from the javascript implementation.

Clone this repository (size: 19.7 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/woadwarrior/bloom/
commit 3: 11c29351165d
parent 2: 805d9a52a443
branch: default
Added jsUnity based unittests.
Jeethu Rao / woadwarrior
14 months ago

Changed (Δ7.8 KB):

raw changeset »

.hgignore (1 lines added, 0 lines removed)

js/bloom.html (49 lines added, 0 lines removed)

js/bloom.js (17 lines added, 20 lines removed)

js/jsunity-0.1.js (239 lines added, 0 lines removed)

Up to file-list .hgignore:

@@ -2,4 +2,5 @@ syntax: glob
2
2
*.pyc
3
3
*.pyo
4
4
*.swp
5
.DS_Store
5
6

Up to file-list js/bloom.html:

7
7
        <h1>Javascript bloom filter</h1>
8
8
        <script type="text/javascript" src="sha256.js"></script>
9
9
        <script type="text/javascript" src="bloom.js"></script>
10
        <script type="text/javascript" src="jsunity-0.1.js"></script>
11
        <script type="text/javascript">
12
            (function() {
13
                function bloomTestSuite() {
14
                    function testUnrle() {
15
                        var rle_data = [["A", 17], ["B", 8], "CCCCCC", ["D", 10], "EEEEEEEkjlfdkfkf", ["1", 8], "233333344444445555555"];
16
                        data = 'AAAAAAAAAAAAAAAAABBBBBBBBCCCCCCDDDDDDDDDDEEEEEEEkjlfdkfkf11111111233333344444445555555';
17
                        var decoded = BloomFilter.unrle(rle_data);
18
                        assertEquals(decoded,data);
19
                    }
20
21
                    function testBloom() {
22
                        var data = {"filter": [["0", 153], "10000100001", ["0", 35], "1", ["0", 34], "10000001", ["0", 238]], "k": 3, "m": 480};
23
                        BloomFilter.prototype.sha256 = sha256_digest;
24
                        var bf = new BloomFilter( data );
25
                        var i=0;
26
                        assertEquals(bf.empty(),false);
27
                        bf.add('Jeethu Rao');
28
                        assertEquals(bf.hasKey('Jeethu Rao'),true);
29
                        bf.remove('Jeethu Rao');
30
                        assertEquals(bf.hasKey('Jeethu Rao'),false);
31
                        var data1 = {'filter':'','k':3,'m':400};
32
                        var bf1 = new BloomFilter( data1 );
33
                        assertEquals(bf1.empty(),true);
34
                        var l = ['Jeethu Rao','Pria Chander','Thilak Raj Rao','Lakshminarayana Kamath'];
35
                        for(i=0;i<l.length;i++) {
36
                            bf1.add(l[i]);
37
                        }
38
                        assertEquals(bf1.empty(),false);
39
                        for(i=0;i<l.length;i++) {
40
                            assertEquals(bf1.hasKey(l[i]),true);
41
                        }
42
                        for(i=0;i<l.length;i++) {
43
                            bf1.remove(l[i]);
44
                        }
45
                        for(i=0;i<l.length;i++) {
46
                            assertEquals(bf1.hasKey(l[i]),false);
47
                        }
48
                        assertEquals(bf1.empty(),true);
49
                    }
50
                }
51
                jsUnity.log = function (s) { 
52
                    var node = document.createElement('div');
53
                    node.innerHTML = s;
54
                    document.body.appendChild(node);
55
                };
56
                var results = jsUnity.run(bloomTestSuite);
57
            })();
58
        </script>
10
59
    </body>
11
60
</html>

Up to file-list js/bloom.js:

51
51
        }
52
52
        var filter = [];
53
53
        var i;
54
        if(d.hasOwnProperty('filter')) {
54
        if(d.hasOwnProperty('filter')&&d.filter) {
55
55
            var min_value = d.hasOwnProperty('min_val') ? d.min_val : 0;
56
56
            var data = unrle(d.filter);
57
57
            var data_len = data.length;
77
77
                throw "Error, incorrect filter len: " + data_len.toString();
78
78
            }
79
79
        } else {
80
            for(i=0;i<m;i++) {
80
            for(i=0;i<this.m;i++) {
81
81
                filter.push(0);
82
82
            }
83
83
        }
90
90
        this.n_bytes = Math.ceil(n_bits/8.0);
91
91
    };
92
92
93
    BloomFilter.prototype.sha256 = sha256_digest;
93
    // BloomFilter.prototype.sha256 = ???;
94
94
95
95
    BloomFilter.prototype.hexToInt = function( s ) {
96
96
        var v = 0;
166
166
        return this._remove( hash, 0 );
167
167
    };
168
168
169
    function _filter_sum( that ) {
170
        var s=0,filter=that.filter;
171
        for(var i=0,j=that.m;i<j;i++) {
172
            if(filter[i]) {
173
                s+=1;
174
            }
175
        }
176
        return s;
177
    };
178
169
179
    BloomFilter.prototype.empty = function() {
180
        return _filter_sum(this)==0;
170
181
    };
171
182
172
183
    BloomFilter.prototype.full = function() {
184
        return _filter_sum(this)==this.m;
173
185
    };
174
186
175
    function test_bloom() {
176
        var data = {"filter": [["0", 153], "10000100001", ["0", 35], "1", ["0", 34], "10000001", ["0", 238]], "k": 3, "m": 480};
177
        var bf = new BloomFilter( data );
178
        console.log(bf.hash("Hello World"));
179
        console.log(bf.hash("Jeethu Rao"));
180
        bf.add('Jeethu Rao');
181
        bf.remove('Jeethu Rao');
182
    }
187
    BloomFilter.unrle = unrle;
183
188
184
    function test_unrle() {
185
        var rle_data = [["A", 17], ["B", 8], "CCCCCC", ["D", 10], "EEEEEEEkjlfdkfkf", ["1", 8], "233333344444445555555"];
186
        data = 'AAAAAAAAAAAAAAAAABBBBBBBBCCCCCCDDDDDDDDDDEEEEEEEkjlfdkfkf11111111233333344444445555555';
187
        var decoded = unrle(rle_data);
188
        return decoded==data;
189
    }
190
    console.log("Test");
191
    console.log(test_unrle());
192
    test_bloom();
189
    window.BloomFilter = BloomFilter;
193
190
})();

Up to file-list js/jsunity-0.1.js:

1
//<%
2
/**
3
 * jsUnity Universal JavaScript Testing Framework v0.1
4
 * http://code.google.com/p/jsunity/
5
 *
6
 * Copyright (c) 2009 Ates Goral
7
 * Licensed under the MIT license.
8
 * http://www.opensource.org/licenses/mit-license.php
9
 */
10
 
11
/**
12
 * Assert that the given Boolean expression evaluates to <code>true</code>
13
 *
14
 * @param expr The Boolean expression
15
 */
16
function assertTrue(expr) {
17
	if (!expr) {
18
		throw "Expression does not evaluate to true";
19
	}
20
}
21
22
/**
23
 * Assert that the given Boolean expression evaluates to <code>false</code>
24
 *
25
 * @param expr The Boolean expression
26
 */
27
function assertFalse(expr) {
28
	if (expr) {
29
		throw "Condition does not evaluate to false";
30
	}
31
}
32
33
/**
34
 * Assert that the given value matches what's expected
35
 *
36
 * @param expected The expected value
37
 * @param actual The actual given value
38
 */
39
function assertEquals(expected, actual) {
40
	if (expected !== actual) {
41
		throw "Actual value does not match what's expected: [expected] "
42
			+ expected + ", [actual] " + actual;
43
	}
44
}
45
46
/**
47
 * Assert that the given value doesn't match the given unexpected value
48
 *
49
 * @param unexpected The unexpected value
50
 * @param actual The actual given value
51
 */
52
function assertNotEquals(unexpected, actual) {
53
	if (unexpected === actual) {
54
		throw "Actual value matches the unexpected value: " + actual;
55
	}
56
}
57
58
/**
59
 * Assert that the given object is <code>null</code>
60
 *
61
 * @param object The given object
62
 */
63
function assertNull(object) {
64
	if (object !== null) {
65
		throw "Object is not null";
66
	}
67
}
68
69
/**
70
 * Assert that the given object is not <code>null</code>
71
 *
72
 * @param object The given object
73
 */
74
function assertNotNull(object) {
75
	if (object === null) {
76
		throw "Object is null";
77
	}
78
}
79
80
/**
81
 * Assert that the given object is <code>undefined</code>
82
 *
83
 * @param object The given object
84
 */
85
function assertUndefined(value) {
86
	if (value !== undefined) {
87
		throw "Value is not undefined";
88
	}
89
}
90
91
/**
92
 * Assert that the given object is not <code>undefined</code>
93
 *
94
 * @param object The given object
95
 */
96
function assertNotUndefined(value) {
97
	if (value === undefined) {
98
		throw "Value is undefined";
99
	}
100
}
101
102
/**
103
 * Assert that the given object is <code>NaN</code>
104
 *
105
 * @param object The given object
106
 */
107
function assertNaN(value) {
108
	if (!isNaN(value)) {
109
		throw "Value is not NaN";
110
	}
111
}
112
113
/**
114
 * Assert that the given object is not <code>NaN</code>
115
 *
116
 * @param object The given object
117
 */
118
function assertNotNaN(value) {
119
	if (isNaN(value)) {
120
		throw "Value is NaN";
121
	}
122
}
123
124
/**
125
 * Fail the test by throwing an exception
126
 */
127
function fail() {
128
	throw "Test failed";
129
}
130
131
(function () {
132
	function parseSuiteFunction(suite) {
133
		var tokens = /^function\s+.+?\{((?:[^}]*}?)+)}$/.exec(
134
			suite.toString().split(/[\r\n]/).join(" "));
135
136
		if (!tokens) {
137
			throw "Invalid function.";
138
		}
139
140
		var runnerBody = tokens[1];
141
142
		var ret = {
143
			runner: new Function("f", runnerBody + "eval(f).call();"),
144
			//name: "",
145
			tests: []
146
		};
147
148
		var fns = runnerBody.match(/function\s+[^(]+/g);
149
150
		if (fns) {
151
			for (var i = 0; i < fns.length; i++) {
152
				var tokens = /\s(.+)$/.exec(fns[i]);
153
154
				if (tokens) {
155
					var name = tokens[1];
156
157
					if (/^test/.test(name)) {
158
						ret.tests.push(name);
159
					} else if (/^setUp|tearDown$/.test(name)) {
160
						ret[name] = true;
161
					}
162
				}
163
			}
164
		}
165
166
		return ret;
167
	}
168
169
	function parseSuite(suite) {
170
		if (suite instanceof Function) {
171
			// functions inside function
172
			return parseSuiteFunction(suite);
173
		} else if (suite instanceof Array) {
174
			// array of test function names
175
			throw "Not implemented";
176
		} else if (suite instanceof Object) {
177
			// functions as properties
178
			throw "Not implemented";
179
		} else if (typeof suite === "string") {
180
			// source code of functions
181
			throw "Not implemented";
182
		} else {
183
			throw "Must be a function, array, object or string.";
184
		}
185
	}
186
187
	jsUnity = {
188
		log: function () {},
189
190
		error: function (s) { this.log("[ERROR] " + s); },
191
192
		run: function (s) {
193
			try {
194
				var suite = parseSuite(s);
195
			} catch (e) {
196
				this.error("Invalid test suite: " + e);
197
				return false;
198
			}
199
200
			var total = suite.tests.length;
201
			var passed = 0;
202
203
			this.log(total + " tests found");
204
205
			for (var i = 0; i < total; i++) {
206
				var test = suite.tests[i];
207
208
				try {
209
					if (suite.setUp) {
210
						suite.runner("setUp");
211
					}
212
					suite.runner(test); // suite.run(i)?
213
					if (suite.tearDown) {
214
						suite.runner("tearDown");
215
					}
216
					passed++;
217
					this.log("[PASSED] " + test);
218
				} catch (e) {
219
					if (suite.tearDown) {
220
						suite.runner("tearDown");
221
					}
222
					this.log("[FAILED] " + test + ": " + e);
223
				}
224
			}
225
226
			var failed = total - passed;
227
228
			this.log(passed + " tests passed");
229
			this.log(failed + " tests failed");
230
231
			return {
232
				total: total,
233
				passed: passed,
234
				failed: failed
235
			}
236
		}
237
	};
238
})();
239
//%>