benschwarz-smoke 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +47 -0
- data/VERSION.yml +2 -2
- data/lib/core_ext/string.rb +6 -0
- data/lib/smoke/cache.rb +38 -23
- data/lib/smoke/request.rb +4 -8
- data/lib/smoke.rb +7 -2
- data/rdoc/classes/Smoke/Origin.html +340 -0
- data/rdoc/classes/Smoke/Source/Data.html +126 -0
- data/rdoc/classes/Smoke/Source/Feed.html +117 -0
- data/rdoc/classes/Smoke/Source/YQL.html +223 -0
- data/rdoc/classes/Smoke.html +260 -0
- data/rdoc/created.rid +1 -0
- data/rdoc/files/README_markdown.html +180 -0
- data/rdoc/files/lib/core_ext/hash_rb.html +49 -0
- data/rdoc/files/lib/smoke/origin_rb.html +49 -0
- data/rdoc/files/lib/smoke/request_rb.html +49 -0
- data/rdoc/files/lib/smoke/source/data_rb.html +49 -0
- data/rdoc/files/lib/smoke/source/feed_rb.html +49 -0
- data/rdoc/files/lib/smoke/source/join_rb.html +49 -0
- data/rdoc/files/lib/smoke/source/yql_rb.html +49 -0
- data/rdoc/files/lib/smoke_rb.html +65 -0
- data/rdoc/fr_class_index.html +21 -0
- data/rdoc/fr_file_index.html +28 -0
- data/rdoc/fr_method_index.html +4459 -0
- data/rdoc/index.html +15 -0
- data/rdoc/rdoc-style.css +319 -0
- data/spec/smoke/cache_spec.rb +28 -6
- data/vendor/crack/History +15 -0
- data/vendor/crack/LICENSE +20 -0
- data/vendor/crack/README.rdoc +42 -0
- data/vendor/crack/Rakefile +49 -0
- data/vendor/crack/VERSION.yml +4 -0
- data/vendor/crack/crack.gemspec +61 -0
- data/vendor/crack/lib/crack/core_extensions.rb +128 -0
- data/vendor/crack/lib/crack/json.rb +68 -0
- data/vendor/crack/lib/crack/xml.rb +214 -0
- data/vendor/crack/lib/crack.rb +7 -0
- data/vendor/crack/test/crack_test.rb +4 -0
- data/vendor/crack/test/data/twittersearch-firefox.json +1 -0
- data/vendor/crack/test/data/twittersearch-ie.json +1 -0
- data/vendor/crack/test/hash_test.rb +56 -0
- data/vendor/crack/test/json_test.rb +66 -0
- data/vendor/crack/test/string_test.rb +31 -0
- data/vendor/crack/test/test_helper.rb +12 -0
- data/vendor/crack/test/xml_test.rb +489 -0
- data/vendor/dependencies/README.markdown +113 -0
- data/vendor/dependencies/Rakefile +5 -0
- data/vendor/dependencies/bin/dep +83 -0
- data/vendor/dependencies/dependencies.gemspec +15 -0
- data/vendor/dependencies/dependencies.gemspec.erb +27 -0
- data/vendor/dependencies/lib/dependencies/dep.rb +99 -0
- data/vendor/dependencies/lib/dependencies.rb +5 -0
- data/vendor/dependencies/test/dependencies_test.rb +228 -0
- data/vendor/dependencies/test/foobaz-0.3.gem +0 -0
- data/vendor/fakeweb/CHANGELOG +163 -0
- data/vendor/fakeweb/LICENSE.txt +281 -0
- data/vendor/fakeweb/README.rdoc +193 -0
- data/vendor/fakeweb/Rakefile +76 -0
- data/vendor/fakeweb/fakeweb.gemspec +21 -0
- data/vendor/fakeweb/lib/fake_web/ext/net_http.rb +71 -0
- data/vendor/fakeweb/lib/fake_web/registry.rb +103 -0
- data/vendor/fakeweb/lib/fake_web/responder.rb +113 -0
- data/vendor/fakeweb/lib/fake_web/response.rb +10 -0
- data/vendor/fakeweb/lib/fake_web/stub_socket.rb +15 -0
- data/vendor/fakeweb/lib/fake_web/utility.rb +22 -0
- data/vendor/fakeweb/lib/fake_web.rb +172 -0
- data/vendor/fakeweb/lib/fakeweb.rb +2 -0
- data/vendor/fakeweb/test/fixtures/google_response_from_curl +12 -0
- data/vendor/fakeweb/test/fixtures/google_response_with_transfer_encoding +17 -0
- data/vendor/fakeweb/test/fixtures/google_response_without_transfer_encoding +11 -0
- data/vendor/fakeweb/test/fixtures/test_example.txt +1 -0
- data/vendor/fakeweb/test/fixtures/test_txt_file +3 -0
- data/vendor/fakeweb/test/test_allow_net_connect.rb +85 -0
- data/vendor/fakeweb/test/test_deprecations.rb +54 -0
- data/vendor/fakeweb/test/test_fake_authentication.rb +92 -0
- data/vendor/fakeweb/test/test_fake_web.rb +535 -0
- data/vendor/fakeweb/test/test_fake_web_open_uri.rb +58 -0
- data/vendor/fakeweb/test/test_helper.rb +74 -0
- data/vendor/fakeweb/test/test_missing_open_uri.rb +25 -0
- data/vendor/fakeweb/test/test_precedence.rb +51 -0
- data/vendor/fakeweb/test/test_query_string.rb +45 -0
- data/vendor/fakeweb/test/test_regexes.rb +103 -0
- data/vendor/fakeweb/test/test_response_headers.rb +73 -0
- data/vendor/fakeweb/test/test_trailing_slashes.rb +53 -0
- data/vendor/fakeweb/test/test_utility.rb +70 -0
- data/vendor/json-1.1.3/CHANGES +93 -0
- data/vendor/json-1.1.3/GPL +340 -0
- data/vendor/json-1.1.3/README +78 -0
- data/vendor/json-1.1.3/RUBY +58 -0
- data/vendor/json-1.1.3/Rakefile +309 -0
- data/vendor/json-1.1.3/TODO +1 -0
- data/vendor/json-1.1.3/VERSION +1 -0
- data/vendor/json-1.1.3/benchmarks/benchmark.txt +133 -0
- data/vendor/json-1.1.3/benchmarks/benchmark_generator.rb +48 -0
- data/vendor/json-1.1.3/benchmarks/benchmark_parser.rb +26 -0
- data/vendor/json-1.1.3/benchmarks/benchmark_rails.rb +26 -0
- data/vendor/json-1.1.3/bin/edit_json.rb +10 -0
- data/vendor/json-1.1.3/bin/prettify_json.rb +76 -0
- data/vendor/json-1.1.3/data/example.json +1 -0
- data/vendor/json-1.1.3/data/index.html +38 -0
- data/vendor/json-1.1.3/data/prototype.js +4184 -0
- data/vendor/json-1.1.3/ext/json/ext/generator/extconf.rb +9 -0
- data/vendor/json-1.1.3/ext/json/ext/generator/generator.c +875 -0
- data/vendor/json-1.1.3/ext/json/ext/generator/unicode.c +182 -0
- data/vendor/json-1.1.3/ext/json/ext/generator/unicode.h +53 -0
- data/vendor/json-1.1.3/ext/json/ext/parser/extconf.rb +9 -0
- data/vendor/json-1.1.3/ext/json/ext/parser/parser.c +1758 -0
- data/vendor/json-1.1.3/ext/json/ext/parser/parser.rl +638 -0
- data/vendor/json-1.1.3/ext/json/ext/parser/unicode.c +154 -0
- data/vendor/json-1.1.3/ext/json/ext/parser/unicode.h +58 -0
- data/vendor/json-1.1.3/install.rb +26 -0
- data/vendor/json-1.1.3/lib/json/Array.xpm +21 -0
- data/vendor/json-1.1.3/lib/json/FalseClass.xpm +21 -0
- data/vendor/json-1.1.3/lib/json/Hash.xpm +21 -0
- data/vendor/json-1.1.3/lib/json/Key.xpm +73 -0
- data/vendor/json-1.1.3/lib/json/NilClass.xpm +21 -0
- data/vendor/json-1.1.3/lib/json/Numeric.xpm +28 -0
- data/vendor/json-1.1.3/lib/json/String.xpm +96 -0
- data/vendor/json-1.1.3/lib/json/TrueClass.xpm +21 -0
- data/vendor/json-1.1.3/lib/json/add/core.rb +135 -0
- data/vendor/json-1.1.3/lib/json/add/rails.rb +58 -0
- data/vendor/json-1.1.3/lib/json/common.rb +354 -0
- data/vendor/json-1.1.3/lib/json/editor.rb +1362 -0
- data/vendor/json-1.1.3/lib/json/ext.rb +13 -0
- data/vendor/json-1.1.3/lib/json/json.xpm +1499 -0
- data/vendor/json-1.1.3/lib/json/pure/generator.rb +394 -0
- data/vendor/json-1.1.3/lib/json/pure/parser.rb +259 -0
- data/vendor/json-1.1.3/lib/json/pure.rb +75 -0
- data/vendor/json-1.1.3/lib/json/version.rb +9 -0
- data/vendor/json-1.1.3/lib/json.rb +235 -0
- data/vendor/json-1.1.3/tests/fixtures/fail1.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail10.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail11.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail12.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail13.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail14.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail18.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail19.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail2.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail20.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail21.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail22.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail23.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail24.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail25.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail27.json +2 -0
- data/vendor/json-1.1.3/tests/fixtures/fail28.json +2 -0
- data/vendor/json-1.1.3/tests/fixtures/fail3.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail4.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail5.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail6.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail7.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail8.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/fail9.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/pass1.json +56 -0
- data/vendor/json-1.1.3/tests/fixtures/pass15.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/pass16.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/pass17.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/pass2.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/pass26.json +1 -0
- data/vendor/json-1.1.3/tests/fixtures/pass3.json +6 -0
- data/vendor/json-1.1.3/tests/runner.rb +25 -0
- data/vendor/json-1.1.3/tests/test_json.rb +293 -0
- data/vendor/json-1.1.3/tests/test_json_addition.rb +161 -0
- data/vendor/json-1.1.3/tests/test_json_fixtures.rb +30 -0
- data/vendor/json-1.1.3/tests/test_json_generate.rb +100 -0
- data/vendor/json-1.1.3/tests/test_json_rails.rb +118 -0
- data/vendor/json-1.1.3/tests/test_json_unicode.rb +61 -0
- data/vendor/json-1.1.3/tools/fuzz.rb +140 -0
- data/vendor/json-1.1.3/tools/server.rb +62 -0
- data/vendor/moneta/LICENSE +20 -0
- data/vendor/moneta/README +51 -0
- data/vendor/moneta/Rakefile +60 -0
- data/vendor/moneta/TODO +4 -0
- data/vendor/moneta/benchmarks/various.rb +234 -0
- data/vendor/moneta/lib/moneta/basic_file.rb +111 -0
- data/vendor/moneta/lib/moneta/berkeley.rb +53 -0
- data/vendor/moneta/lib/moneta/couch.rb +63 -0
- data/vendor/moneta/lib/moneta/datamapper.rb +117 -0
- data/vendor/moneta/lib/moneta/file.rb +91 -0
- data/vendor/moneta/lib/moneta/lmc.rb +52 -0
- data/vendor/moneta/lib/moneta/memcache.rb +53 -0
- data/vendor/moneta/lib/moneta/memory.rb +11 -0
- data/vendor/moneta/lib/moneta/mongodb.rb +58 -0
- data/vendor/moneta/lib/moneta/redis.rb +49 -0
- data/vendor/moneta/lib/moneta/rufus.rb +41 -0
- data/vendor/moneta/lib/moneta/s3.rb +162 -0
- data/vendor/moneta/lib/moneta/sdbm.rb +33 -0
- data/vendor/moneta/lib/moneta/tyrant.rb +58 -0
- data/vendor/moneta/lib/moneta/xattr.rb +58 -0
- data/vendor/moneta/lib/moneta.rb +76 -0
- data/vendor/moneta/moneta.gemspec +32 -0
- data/vendor/moneta/script/destroy +14 -0
- data/vendor/moneta/script/generate +14 -0
- data/vendor/moneta/spec/moneta_basic_file_spec.rb +50 -0
- data/vendor/moneta/spec/moneta_berkeley_spec.rb +20 -0
- data/vendor/moneta/spec/moneta_couch_spec.rb +22 -0
- data/vendor/moneta/spec/moneta_datamapper_spec.rb +79 -0
- data/vendor/moneta/spec/moneta_file_spec.rb +21 -0
- data/vendor/moneta/spec/moneta_lmc_spec.rb +24 -0
- data/vendor/moneta/spec/moneta_memcache_spec.rb +16 -0
- data/vendor/moneta/spec/moneta_memory_spec.rb +12 -0
- data/vendor/moneta/spec/moneta_mongodb_spec.rb +16 -0
- data/vendor/moneta/spec/moneta_redis_spec.rb +16 -0
- data/vendor/moneta/spec/moneta_rufus_spec.rb +15 -0
- data/vendor/moneta/spec/moneta_s3_spec.rb +19 -0
- data/vendor/moneta/spec/moneta_sdbm_spec.rb +21 -0
- data/vendor/moneta/spec/moneta_tyrant_spec.rb +15 -0
- data/vendor/moneta/spec/moneta_xattr_spec.rb +21 -0
- data/vendor/moneta/spec/shared.rb +122 -0
- data/vendor/moneta/spec/spec_helper.rb +7 -0
- data/vendor/rest-client/README.rdoc +151 -0
- data/vendor/rest-client/Rakefile +58 -0
- data/vendor/rest-client/VERSION +1 -0
- data/vendor/rest-client/bin/restclient +87 -0
- data/vendor/rest-client/lib/rest_client.rb +2 -0
- data/vendor/rest-client/lib/restclient/exceptions.rb +88 -0
- data/vendor/rest-client/lib/restclient/mixin/response.rb +43 -0
- data/vendor/rest-client/lib/restclient/raw_response.rb +30 -0
- data/vendor/rest-client/lib/restclient/request.rb +238 -0
- data/vendor/rest-client/lib/restclient/resource.rb +146 -0
- data/vendor/rest-client/lib/restclient/response.rb +20 -0
- data/vendor/rest-client/lib/restclient.rb +99 -0
- data/vendor/rest-client/rest-client.gemspec +66 -0
- data/vendor/rest-client/spec/base.rb +4 -0
- data/vendor/rest-client/spec/exceptions_spec.rb +65 -0
- data/vendor/rest-client/spec/mixin/response_spec.rb +46 -0
- data/vendor/rest-client/spec/raw_response_spec.rb +17 -0
- data/vendor/rest-client/spec/request_spec.rb +476 -0
- data/vendor/rest-client/spec/resource_spec.rb +75 -0
- data/vendor/rest-client/spec/response_spec.rb +16 -0
- data/vendor/rest-client/spec/restclient_spec.rb +53 -0
- data/vendor/simple-rss/LICENSE +429 -0
- data/vendor/simple-rss/README +43 -0
- data/vendor/simple-rss/Rakefile +212 -0
- data/vendor/simple-rss/install.rb +40 -0
- data/vendor/simple-rss/lib/simple-rss.rb +150 -0
- data/vendor/simple-rss/simple-rss.gemspec +12 -0
- data/vendor/simple-rss/test/base/base_test.rb +51 -0
- data/vendor/simple-rss/test/data/atom.xml +45 -0
- data/vendor/simple-rss/test/data/not-rss.xml +8 -0
- data/vendor/simple-rss/test/data/rss09.rdf +79 -0
- data/vendor/simple-rss/test/data/rss20.xml +818 -0
- data/vendor/simple-rss/test/test_helper.rb +4 -0
- metadata +314 -40
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
class TC_JSONUnicode < Test::Unit::TestCase
|
7
|
+
include JSON
|
8
|
+
|
9
|
+
def setup
|
10
|
+
$KCODE = 'UTF8'
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_unicode
|
14
|
+
assert_equal '""', ''.to_json
|
15
|
+
assert_equal '"\\b"', "\b".to_json
|
16
|
+
assert_equal '"\u0001"', 0x1.chr.to_json
|
17
|
+
assert_equal '"\u001f"', 0x1f.chr.to_json
|
18
|
+
assert_equal '" "', ' '.to_json
|
19
|
+
assert_equal "\"#{0x7f.chr}\"", 0x7f.chr.to_json
|
20
|
+
utf8 = [ "© ≠ €! \01" ]
|
21
|
+
json = '["\u00a9 \u2260 \u20ac! \u0001"]'
|
22
|
+
assert_equal json, utf8.to_json
|
23
|
+
assert_equal utf8, parse(json)
|
24
|
+
utf8 = ["\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212"]
|
25
|
+
json = "[\"\\u3042\\u3044\\u3046\\u3048\\u304a\"]"
|
26
|
+
assert_equal json, utf8.to_json
|
27
|
+
assert_equal utf8, parse(json)
|
28
|
+
utf8 = ['საქართველო']
|
29
|
+
json = "[\"\\u10e1\\u10d0\\u10e5\\u10d0\\u10e0\\u10d7\\u10d5\\u10d4\\u10da\\u10dd\"]"
|
30
|
+
assert_equal json, utf8.to_json
|
31
|
+
assert_equal utf8, parse(json)
|
32
|
+
assert_equal '["\\u00c3"]', JSON.generate(["Ã"])
|
33
|
+
assert_equal ["€"], JSON.parse('["\u20ac"]')
|
34
|
+
utf8 = ["\xf0\xa0\x80\x81"]
|
35
|
+
json = '["\ud840\udc01"]'
|
36
|
+
assert_equal json, JSON.generate(utf8)
|
37
|
+
assert_equal utf8, JSON.parse(json)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_chars
|
41
|
+
(0..0x7f).each do |i|
|
42
|
+
json = '["\u%04x"]' % i
|
43
|
+
if RUBY_VERSION >= "1.9."
|
44
|
+
i = i.chr
|
45
|
+
end
|
46
|
+
assert_equal i, JSON.parse(json).first[0]
|
47
|
+
if i == ?\b
|
48
|
+
generated = JSON.generate(["" << i])
|
49
|
+
assert '["\b"]' == generated || '["\10"]' == generated
|
50
|
+
elsif [?\n, ?\r, ?\t, ?\f].include?(i)
|
51
|
+
assert_equal '[' << ('' << i).dump << ']', JSON.generate(["" << i])
|
52
|
+
elsif i.chr < 0x20.chr
|
53
|
+
assert_equal json, JSON.generate(["" << i])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
assert_raises(JSON::GeneratorError) do
|
57
|
+
JSON.generate(["" << 0x80])
|
58
|
+
end
|
59
|
+
assert_equal "\302\200", JSON.parse('["\u0080"]').first
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
$KCODE='UTF8'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'iconv'
|
5
|
+
ISO_8859_1_TO_UTF8 = Iconv.new('utf-8', 'iso-8859-15')
|
6
|
+
class ::String
|
7
|
+
def to_utf8
|
8
|
+
ISO_8859_1_TO_UTF8.iconv self
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Fuzzer
|
13
|
+
def initialize(n, freqs = {})
|
14
|
+
sum = freqs.inject(0.0) { |s, x| s + x.last }
|
15
|
+
freqs.each_key { |x| freqs[x] /= sum }
|
16
|
+
s = 0.0
|
17
|
+
freqs.each_key do |x|
|
18
|
+
freqs[x] = s .. (s + t = freqs[x])
|
19
|
+
s += t
|
20
|
+
end
|
21
|
+
@freqs = freqs
|
22
|
+
@n = n
|
23
|
+
@alpha = (0..0xff).to_a
|
24
|
+
end
|
25
|
+
|
26
|
+
def random_string
|
27
|
+
s = ''
|
28
|
+
30.times { s << @alpha[rand(@alpha.size)] }
|
29
|
+
s.to_utf8
|
30
|
+
end
|
31
|
+
|
32
|
+
def pick
|
33
|
+
r = rand
|
34
|
+
found = @freqs.find { |k, f| f.include? rand }
|
35
|
+
found && found.first
|
36
|
+
end
|
37
|
+
|
38
|
+
def make_pick
|
39
|
+
k = pick
|
40
|
+
case
|
41
|
+
when k == Hash, k == Array
|
42
|
+
k.new
|
43
|
+
when k == true, k == false, k == nil
|
44
|
+
k
|
45
|
+
when k == String
|
46
|
+
random_string
|
47
|
+
when k == Fixnum
|
48
|
+
rand(2 ** 30) - 2 ** 29
|
49
|
+
when k == Bignum
|
50
|
+
rand(2 ** 70) - 2 ** 69
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def fuzz(current = nil)
|
55
|
+
if @n > 0
|
56
|
+
case current
|
57
|
+
when nil
|
58
|
+
@n -= 1
|
59
|
+
current = fuzz [ Hash, Array ][rand(2)].new
|
60
|
+
when Array
|
61
|
+
while @n > 0
|
62
|
+
@n -= 1
|
63
|
+
current << case p = make_pick
|
64
|
+
when Array, Hash
|
65
|
+
fuzz(p)
|
66
|
+
else
|
67
|
+
p
|
68
|
+
end
|
69
|
+
end
|
70
|
+
when Hash
|
71
|
+
while @n > 0
|
72
|
+
@n -= 1
|
73
|
+
current[random_string] = case p = make_pick
|
74
|
+
when Array, Hash
|
75
|
+
fuzz(p)
|
76
|
+
else
|
77
|
+
p
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
current
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class MyState < JSON.state
|
87
|
+
WS = " \r\t\n"
|
88
|
+
|
89
|
+
def initialize
|
90
|
+
super(
|
91
|
+
:indent => make_spaces,
|
92
|
+
:space => make_spaces,
|
93
|
+
:space_before => make_spaces,
|
94
|
+
:object_nl => make_spaces,
|
95
|
+
:array_nl => make_spaces,
|
96
|
+
:max_nesting => false
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
def make_spaces
|
101
|
+
s = ''
|
102
|
+
rand(1).times { s << WS[rand(WS.size)] }
|
103
|
+
s
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
n = (ARGV.shift || 500).to_i
|
108
|
+
loop do
|
109
|
+
fuzzer = Fuzzer.new(n,
|
110
|
+
Hash => 25,
|
111
|
+
Array => 25,
|
112
|
+
String => 10,
|
113
|
+
Fixnum => 10,
|
114
|
+
Bignum => 10,
|
115
|
+
nil => 5,
|
116
|
+
true => 5,
|
117
|
+
false => 5
|
118
|
+
)
|
119
|
+
o1 = fuzzer.fuzz
|
120
|
+
json = JSON.generate o1, MyState.new
|
121
|
+
if $DEBUG
|
122
|
+
puts "-" * 80
|
123
|
+
puts json, json.size
|
124
|
+
else
|
125
|
+
puts json.size
|
126
|
+
end
|
127
|
+
begin
|
128
|
+
o2 = JSON.parse(json, :max_nesting => false)
|
129
|
+
rescue JSON::ParserError => e
|
130
|
+
puts "Caught #{e.class}: #{e.message}\n#{e.backtrace * "\n"}"
|
131
|
+
puts "o1 = #{o1.inspect}", "json = #{json}", "json_str = #{json.inspect}"
|
132
|
+
puts "locals = #{local_variables.inspect}"
|
133
|
+
exit
|
134
|
+
end
|
135
|
+
if o1 != o2
|
136
|
+
puts "mismatch", "o1 = #{o1.inspect}", "o2 = #{o2.inspect}",
|
137
|
+
"json = #{json}", "json_str = #{json.inspect}"
|
138
|
+
puts "locals = #{local_variables.inspect}"
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE='UTF8'
|
4
|
+
require 'webrick'
|
5
|
+
include WEBrick
|
6
|
+
$:.unshift 'ext'
|
7
|
+
$:.unshift 'lib'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
class JSONServlet < HTTPServlet::AbstractServlet
|
11
|
+
@@count = 1
|
12
|
+
|
13
|
+
def do_GET(req, res)
|
14
|
+
obj = {
|
15
|
+
"TIME" => Time.now.strftime("%FT%T"),
|
16
|
+
"foo" => "Bär",
|
17
|
+
"bar" => "© ≠ €!",
|
18
|
+
'a' => 2,
|
19
|
+
'b' => 3.141,
|
20
|
+
'COUNT' => @@count += 1,
|
21
|
+
'c' => 'c',
|
22
|
+
'd' => [ 1, "b", 3.14 ],
|
23
|
+
'e' => { 'foo' => 'bar' },
|
24
|
+
'g' => "松本行弘",
|
25
|
+
'h' => 1000.0,
|
26
|
+
'i' => 0.001,
|
27
|
+
'j' => "\xf0\xa0\x80\x81",
|
28
|
+
}
|
29
|
+
res.body = JSON.generate obj
|
30
|
+
res['Content-Type'] = "application/json"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_server(err, dir, port)
|
35
|
+
dir = File.expand_path(dir)
|
36
|
+
err.puts "Surf to:", "http://#{Socket.gethostname}:#{port}"
|
37
|
+
|
38
|
+
s = HTTPServer.new(
|
39
|
+
:Port => port,
|
40
|
+
:DocumentRoot => dir,
|
41
|
+
:Logger => WEBrick::Log.new(err),
|
42
|
+
:AccessLog => [
|
43
|
+
[ err, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
|
44
|
+
[ err, WEBrick::AccessLog::REFERER_LOG_FORMAT ],
|
45
|
+
[ err, WEBrick::AccessLog::AGENT_LOG_FORMAT ]
|
46
|
+
]
|
47
|
+
)
|
48
|
+
s.mount("/json", JSONServlet)
|
49
|
+
s
|
50
|
+
end
|
51
|
+
|
52
|
+
default_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'data'))
|
53
|
+
dir = ARGV.shift || default_dir
|
54
|
+
port = (ARGV.shift || 6666).to_i
|
55
|
+
s = create_server(STDERR, dir, 6666)
|
56
|
+
t = Thread.new { s.start }
|
57
|
+
trap(:INT) do
|
58
|
+
s.shutdown
|
59
|
+
t.join
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
sleep
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Yehuda Katz
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,51 @@
|
|
1
|
+
Moneta: A unified interface for key/value stores
|
2
|
+
================================================
|
3
|
+
|
4
|
+
Moneta provides a standard interface for interacting with various kinds of key/value stores.
|
5
|
+
|
6
|
+
Out of the box, it supports:
|
7
|
+
|
8
|
+
* File store for xattr
|
9
|
+
* Basic File Store
|
10
|
+
* Memcache store
|
11
|
+
* In-memory store
|
12
|
+
* The xattrs in a file system
|
13
|
+
* DataMapper
|
14
|
+
* S3
|
15
|
+
* Berkeley DB
|
16
|
+
* Redis
|
17
|
+
* SDBM
|
18
|
+
* Tokyo
|
19
|
+
* CouchDB
|
20
|
+
|
21
|
+
All stores support key expiration, but only memcache supports it natively. All other stores
|
22
|
+
emulate expiration.
|
23
|
+
|
24
|
+
The Moneta API is purposely extremely similar to the Hash API. In order so support an
|
25
|
+
identical API across stores, it does not support iteration or partial matches, but that
|
26
|
+
might come in a future release.
|
27
|
+
|
28
|
+
The API:
|
29
|
+
|
30
|
+
#initialize(options):: options differs per-store, and is used to set up the store
|
31
|
+
|
32
|
+
#[](key):: retrieve a key. if the key is not available, return nil
|
33
|
+
|
34
|
+
#[]=(key, value):: set a value for a key. if the key is already used, clobber it.
|
35
|
+
keys set using []= will never expire
|
36
|
+
|
37
|
+
#delete(key):: delete the key from the store and return the current value
|
38
|
+
|
39
|
+
#key?(key):: true if the key exists, false if it does not
|
40
|
+
|
41
|
+
#has_key?(key):: alias for key?
|
42
|
+
|
43
|
+
#store(key, value, options):: same as []=, but you can supply an :expires_in option,
|
44
|
+
which will specify a number of seconds before the key
|
45
|
+
should expire. In order to support the same features
|
46
|
+
across all stores, only full seconds are supported
|
47
|
+
|
48
|
+
#update_key(key, options):: updates an existing key with a new :expires_in option.
|
49
|
+
if the key has already expired, it will not be updated.
|
50
|
+
|
51
|
+
#clear:: clear all keys in this store
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rubygems/specification'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
GEM = "moneta"
|
8
|
+
GEM_VERSION = "0.5.0"
|
9
|
+
AUTHOR = "Yehuda Katz"
|
10
|
+
EMAIL = "wycats@gmail.com"
|
11
|
+
HOMEPAGE = "http://www.yehudakatz.com"
|
12
|
+
SUMMARY = "A unified interface to key/value stores"
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.name = GEM
|
16
|
+
s.version = GEM_VERSION
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.has_rdoc = true
|
19
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
20
|
+
s.summary = SUMMARY
|
21
|
+
s.description = s.summary
|
22
|
+
s.author = AUTHOR
|
23
|
+
s.email = EMAIL
|
24
|
+
s.homepage = HOMEPAGE
|
25
|
+
|
26
|
+
# Uncomment this to add a dependency
|
27
|
+
# s.add_dependency "foo"
|
28
|
+
|
29
|
+
s.require_path = 'lib'
|
30
|
+
s.autorequire = GEM
|
31
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
|
32
|
+
end
|
33
|
+
|
34
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
35
|
+
pkg.gem_spec = spec
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "install the gem locally"
|
39
|
+
task :install => [:package] do
|
40
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "create a gemspec file"
|
44
|
+
task :make_spec do
|
45
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
46
|
+
file.puts spec.to_ruby
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Run all examples (or a specific spec with TASK=xxxx)"
|
51
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
52
|
+
t.spec_opts = ["-cfs"]
|
53
|
+
t.spec_files = begin
|
54
|
+
if ENV["TASK"]
|
55
|
+
ENV["TASK"].split(',').map { |task| "spec/**/#{task}_spec.rb" }
|
56
|
+
else
|
57
|
+
FileList['spec/**/*_spec.rb']
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/vendor/moneta/TODO
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'benchmark'
|
3
|
+
require "rubygems"
|
4
|
+
|
5
|
+
# Hacked arrays
|
6
|
+
# Array modifications
|
7
|
+
class HackedArray < Array
|
8
|
+
# Random keys/values
|
9
|
+
attr_reader :keys_used
|
10
|
+
def random_key(no_repeat = true, clean_keys_used = false)
|
11
|
+
@keys_used = [] if clean_keys_used or @keys_used.nil? or @keys_used.size == self.size
|
12
|
+
begin key = rand(self.size) end while no_repeat and @keys_used.include?(key)
|
13
|
+
@keys_used << key
|
14
|
+
return key
|
15
|
+
end
|
16
|
+
|
17
|
+
def random_value(no_repeat = true, clean_keys_used = false)
|
18
|
+
values_at(random_key(no_repeat, clean_keys_used)).first
|
19
|
+
end
|
20
|
+
alias_method :random, :random_value
|
21
|
+
|
22
|
+
def random_subset(n, no_repeat = true, clean_keys_used = true)
|
23
|
+
(1..n).map{|x| random_value(no_repeat, (clean_keys_used && x == 1))}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.new_from_string(str)
|
27
|
+
res = new
|
28
|
+
str.split('').each{|x| res << x}
|
29
|
+
res
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
require "../lib/moneta"
|
34
|
+
require "moneta/memcache"
|
35
|
+
require "moneta/tyrant"
|
36
|
+
require "moneta/berkeley"
|
37
|
+
|
38
|
+
|
39
|
+
stores = {
|
40
|
+
'Redis' => { },
|
41
|
+
'Memcached' => { :class_name => "Memcache", :server => "localhost:11211", :namespace => 'moneta_bench' },
|
42
|
+
'Tyrant' => { :host => 'localhost', :port => 1978 }, # Breaks for any n > 50 on my machine
|
43
|
+
'MongoDB' => { :host => 'localhost', :port => 27017, :db => 'moneta_bench' },
|
44
|
+
'LMC' => { :filename => "bench.lmc" },
|
45
|
+
'Berkeley' => { :file => "bench.bdb" },
|
46
|
+
'Rufus' => {:file => "bench.rufus"},
|
47
|
+
'Memory' => { },
|
48
|
+
'DataMapper' => { :setup => "sqlite3::memory:" },
|
49
|
+
# 'Couch' => {:db => "couch_test"},
|
50
|
+
'TC (Tyrant)' =>
|
51
|
+
{:name => "test.tieredtyrant", :backup => Moneta::Tyrant.new(:host => "localhost", :port => 1978), :class_name => "TieredCache"},
|
52
|
+
'TC (Memcached)' =>
|
53
|
+
{:name => "test.tieredmc", :backup => Moneta::Memcache.new(:server => "localhost:11211", :namespace => "various"), :class_name => "TieredCache"}
|
54
|
+
}
|
55
|
+
|
56
|
+
stats, keys, data, errors, summary = {}, [], HackedArray.new, HackedArray.new, HackedArray.new
|
57
|
+
dict = HackedArray.new_from_string 'abcdefghijklnopq123456789'
|
58
|
+
n = ARGV[0] ? ARGV[0].to_i : 100
|
59
|
+
m = ARGV[1] ? ARGV[1].to_i : 10
|
60
|
+
c = ARGV[2] ? ARGV[2].to_i : 3
|
61
|
+
vlen_min, vlen_max, vlen_ttl, vlen_avg = 99999, 0, 0, 0
|
62
|
+
ds = dict.size
|
63
|
+
|
64
|
+
puts "======================================================================"
|
65
|
+
puts "Comparison of write/read between Moneta Stores"
|
66
|
+
puts "======================================================================"
|
67
|
+
|
68
|
+
puts "Data loading..."
|
69
|
+
n.times do |x|
|
70
|
+
klen = 6 + rand(3)
|
71
|
+
vlen = (rand(m) + 1) * (rand(m) + rand(m) + 1)
|
72
|
+
key = dict.random_subset(klen).join
|
73
|
+
keys << key
|
74
|
+
value = key * vlen
|
75
|
+
data << [key, value]
|
76
|
+
vs = value.size
|
77
|
+
vlen_min = vs if vs < vlen_min
|
78
|
+
vlen_max = vs if vs > vlen_max
|
79
|
+
vlen_ttl = vlen_ttl + vs
|
80
|
+
end
|
81
|
+
vlen_avg = vlen_ttl / n
|
82
|
+
|
83
|
+
puts "----------------------------------------------------------------------"
|
84
|
+
#puts data.inspect
|
85
|
+
puts "Total keys: #{keys.size}, unique: #{keys.uniq.size}"
|
86
|
+
#puts keys.sort.inspect
|
87
|
+
|
88
|
+
puts "----------------------------------------------------------------------"
|
89
|
+
puts " Minimum Maximum Total Average xps "
|
90
|
+
puts "----------------------------------------------------------------------"
|
91
|
+
puts "Lenght Stats % 10i % 10i % 10i % 10i " % [vlen_min, vlen_max, vlen_ttl, vlen_avg]
|
92
|
+
|
93
|
+
module Moneta
|
94
|
+
class TieredCache
|
95
|
+
include Moneta::Defaults
|
96
|
+
|
97
|
+
def initialize(options)
|
98
|
+
@bdb = Moneta::Berkeley.new(:file => File.join(File.dirname(__FILE__), options[:name]))
|
99
|
+
@mc = options[:backup]
|
100
|
+
# @mc = Moneta::Tyrant.new(:host => "localhost", :port => 1978)
|
101
|
+
# @mc = Moneta::Memcache.new(:server => "localhost:11211", :namespace => options[:name])
|
102
|
+
end
|
103
|
+
|
104
|
+
def [](key)
|
105
|
+
val = @bdb[key]
|
106
|
+
unless val
|
107
|
+
@bdb[key] = val if val = @mc[key]
|
108
|
+
end
|
109
|
+
val
|
110
|
+
end
|
111
|
+
|
112
|
+
def []=(key, val)
|
113
|
+
@bdb[key] = val
|
114
|
+
@mc[key] = val
|
115
|
+
end
|
116
|
+
|
117
|
+
def store(key, value, options = {})
|
118
|
+
@bdb.store(key, value, options)
|
119
|
+
@mc.store(key, value, options)
|
120
|
+
end
|
121
|
+
|
122
|
+
def delete(key)
|
123
|
+
bdb_val = @bdb.delete(key)
|
124
|
+
mc_val = @mc.delete(key)
|
125
|
+
bdb_val || mc_val
|
126
|
+
end
|
127
|
+
|
128
|
+
def clear
|
129
|
+
@mc.clear
|
130
|
+
@bdb.clear
|
131
|
+
end
|
132
|
+
|
133
|
+
def update_key(name, options)
|
134
|
+
@mc.update_key(name, options)
|
135
|
+
@bdb.update_key(name, options)
|
136
|
+
end
|
137
|
+
|
138
|
+
def key?(key)
|
139
|
+
@bdb.key?(key) || @mc.key?(key)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
stores.each do |name, options|
|
145
|
+
cname = options.delete(:class_name) || name
|
146
|
+
puts "======================================================================"
|
147
|
+
puts name
|
148
|
+
puts "----------------------------------------------------------------------"
|
149
|
+
begin
|
150
|
+
require "../lib/moneta/#{cname.downcase}"
|
151
|
+
rescue LoadError
|
152
|
+
end
|
153
|
+
klass = Moneta.const_get(cname)
|
154
|
+
@cache = klass.new(options)
|
155
|
+
stats[name] = {
|
156
|
+
:writes => [],
|
157
|
+
:reads => [],
|
158
|
+
:totals => [],
|
159
|
+
:avgs => [],
|
160
|
+
}
|
161
|
+
c.times do |round|
|
162
|
+
@cache.clear
|
163
|
+
print "[#{round + 1}] R"
|
164
|
+
m1 = Benchmark.measure do
|
165
|
+
n.times do
|
166
|
+
key, value = data.random
|
167
|
+
|
168
|
+
@cache[key] = value
|
169
|
+
end
|
170
|
+
end
|
171
|
+
stats[name][:writes] << m1.real
|
172
|
+
print "W "
|
173
|
+
m2 = Benchmark.measure do
|
174
|
+
n.times do
|
175
|
+
key, value = data.random
|
176
|
+
res = @cache[key]
|
177
|
+
errors << [name, key, value, res] unless res == value
|
178
|
+
end
|
179
|
+
end
|
180
|
+
stats[name][:reads] << m2.real
|
181
|
+
stats[name][:totals] << (m1.real + m2.real)
|
182
|
+
stats[name][:avgs] << (m1.real + m2.real)
|
183
|
+
end
|
184
|
+
print "\n"
|
185
|
+
puts "----------------------------------------------------------------------"
|
186
|
+
puts " Minimum Maximum Total Average xps "
|
187
|
+
puts "----------------------------------------------------------------------"
|
188
|
+
tcmin, tcmax, tctot, tcavg = 99999, 0, 0, 0
|
189
|
+
[:writes, :reads].each do |sname|
|
190
|
+
cmin, cmax, ctot, cavg = 99999, 0, 0, 0
|
191
|
+
stats[name][sname].each do |val|
|
192
|
+
cmin = val if val < cmin
|
193
|
+
tcmin = val if val < tcmin
|
194
|
+
cmax = val if val > cmax
|
195
|
+
tcmax = val if val > tcmax
|
196
|
+
ctot = ctot + val
|
197
|
+
tctot = tctot + val
|
198
|
+
end
|
199
|
+
cavg = ctot / c
|
200
|
+
puts "%-14.14s % 10.4f % 10.4f % 10.4f % 10.4f % 10.4f " % ["#{name} #{sname}", cmin, cmax, ctot, cavg, n / cavg]
|
201
|
+
end
|
202
|
+
tcavg = tctot / (c * 2)
|
203
|
+
puts "%-14.14s % 10.4f % 10.4f % 10.4f % 10.4f % 10.4f " % ["#{name} avgs", tcmin, tcmax, tctot, tcavg, n / tcavg]
|
204
|
+
summary << [name, tcmin, tcmax, tctot, tcavg, n / tcavg]
|
205
|
+
end
|
206
|
+
puts "----------------------------------------------------------------------"
|
207
|
+
if errors.size > 0
|
208
|
+
puts "Errors : #{errors.size}"
|
209
|
+
# puts errors.inspect
|
210
|
+
else
|
211
|
+
puts "No errors in reading!"
|
212
|
+
end
|
213
|
+
puts "======================================================================"
|
214
|
+
puts "Summary :: #{c} runs, #{n} keys"
|
215
|
+
puts "======================================================================"
|
216
|
+
puts " Minimum Maximum Total Average xps "
|
217
|
+
puts "----------------------------------------------------------------------"
|
218
|
+
summary.each do |sry|
|
219
|
+
puts "%-14.14s % 10.4f % 10.4f % 10.4f % 10.4f % 10.4f " % sry
|
220
|
+
end
|
221
|
+
puts "======================================================================"
|
222
|
+
puts "THE END"
|
223
|
+
puts "======================================================================"
|
224
|
+
|
225
|
+
#======================================================================
|
226
|
+
#Summary :: 3 runs, 1000 keys
|
227
|
+
#======================================================================
|
228
|
+
# Minimum Maximum Total Average xps
|
229
|
+
#----------------------------------------------------------------------
|
230
|
+
#MemcacheDB 0.6202 2.7850 7.0099 1.1683 855.9366
|
231
|
+
#Memcached 0.4483 0.6563 3.3251 0.5542 1804.4385
|
232
|
+
#Redis 0.3282 0.5221 2.2965 0.3828 2612.6444
|
233
|
+
#MongoDB 0.6660 1.0539 5.1667 0.8611 1161.2745
|
234
|
+
#======================================================================
|