joust 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +19 -0
- data/README.rdoc +54 -0
- data/Rakefile +8 -0
- data/bin/joust +42 -0
- data/data/specifications.yml +126 -0
- data/lib/joust.rb +45 -0
- data/lib/joust/expected_response.rb +20 -0
- data/lib/joust/expected_response/version_12.rb +10 -0
- data/lib/joust/expected_response/version_20.rb +10 -0
- data/spec/joust_spec.rb +41 -0
- data/spec/spec_helper.rb +2 -0
- metadata +63 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012 Vertive, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= Joust - A JSON-RPC Server testing utility
|
2
|
+
|
3
|
+
== What is JSON-RPC?
|
4
|
+
From the [JSON-RPC Spec](http://www.jsonrpc.org/spec.html):
|
5
|
+
|
6
|
+
"JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this specification defines several data structures and the rules around their processing.
|
7
|
+
It is transport agnostic in that the concepts can be used within the same process, over sockets, over http, or in many various message passing environments. It uses JSON (RFC 4627)
|
8
|
+
as data format. It is designed to be simple!"
|
9
|
+
|
10
|
+
== What is Joust good for?
|
11
|
+
There are many JSON-RPC frameworks available for a variety of languages, but it can be difficult to tell which ones truly conform to specifications. Joust is a utility that allows a user or
|
12
|
+
developer to determine if a particular framework meets these specifications (and if it does not it enumerates how the framework failed).
|
13
|
+
|
14
|
+
== What versions of JSON-RPC specifications can I test for?
|
15
|
+
Joust supports testing for JSON-RPC [v1.2](http://jsonrpc.org/historical/jsonrpc12_proposal.html#specification) and [v2.0](http://www.jsonrpc.org/spec.html) (v2.0 is used by default).
|
16
|
+
|
17
|
+
== How do I use Joust?
|
18
|
+
JSON-RPC tests a server framework by sending predetermined requests and examining the server's response versus the expected response. To use Joust, set up a JSON-RPC Server that supports the
|
19
|
+
following methods (and ONLY the following methods):
|
20
|
+
|
21
|
+
* subtract: takes two parameters and returns difference between the first minus the second
|
22
|
+
* subtract_named: takes two named parameters ('minuend' and 'subtrahend') in any order and subtracts minuend minus subtrahend.
|
23
|
+
* update: takes five parameters and does nothing
|
24
|
+
* foobar: takes no parameters and does nothing
|
25
|
+
* sum: takes three parameters and returns their sum
|
26
|
+
* notify_hello: takes one parameter and does nothing
|
27
|
+
* get_data: takes no paramters and returns an array of 'hello' and 5
|
28
|
+
* notify_sum: takes three parameters and does nothing
|
29
|
+
|
30
|
+
Examples of a PHP class and a Ruby class with the above methods defined can be found in the example directory of [the Github repo](https://github.com/EvilScott/joust). Note that all of these
|
31
|
+
methods are used to test a JSON-RPC v2.0 server, but only a subset of them are used to test v1.2.
|
32
|
+
|
33
|
+
After setting this up just point Joust at the server and check out the results:
|
34
|
+
|
35
|
+
joust <JSON-RPC server url>
|
36
|
+
|
37
|
+
The results should look something like this:
|
38
|
+
|
39
|
+
v2.0 Positional parameters (1/2) -- PASS
|
40
|
+
v2.0 Positional parameters (2/2) -- PASS
|
41
|
+
v2.0 Named parameters (1/2) -- PASS
|
42
|
+
v2.0 Named parameters (2/2) -- PASS
|
43
|
+
v2.0 Notification (1/2) -- PASS
|
44
|
+
v2.0 Notification (2/2) -- PASS
|
45
|
+
v2.0 Missing method -- PASS
|
46
|
+
v2.0 Invalid JSON -- PASS
|
47
|
+
v2.0 Invalid JSON-RPC -- PASS
|
48
|
+
v2.0 Invalid batch JSON -- PASS
|
49
|
+
v2.0 Empty array -- PASS
|
50
|
+
v2.0 Invalid batch JSON-RPC (1/2) -- PASS
|
51
|
+
v2.0 Invalid batch JSON-RPC (2/2) -- PASS
|
52
|
+
v2.0 Batch call -- PASS
|
53
|
+
v2.0 Batch call (all notifications) -- PASS
|
54
|
+
JSON-RPC v2.0: 15/15 tests passed
|
data/Rakefile
ADDED
data/bin/joust
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Joust - JSON-RPC Server Specification Testing
|
3
|
+
# R. Scott Reis - February 2012
|
4
|
+
|
5
|
+
# core joust code
|
6
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
7
|
+
require 'joust'
|
8
|
+
|
9
|
+
# check for valid URL
|
10
|
+
url = ARGV.first
|
11
|
+
begin
|
12
|
+
URI.parse(url)
|
13
|
+
rescue
|
14
|
+
puts "URL #{url} does not appear to be valid"
|
15
|
+
exit(1)
|
16
|
+
end
|
17
|
+
|
18
|
+
# default options
|
19
|
+
options = {:version => 'v2.0'}
|
20
|
+
|
21
|
+
# command line options
|
22
|
+
require 'optparse'
|
23
|
+
OptionParser.new do |opts|
|
24
|
+
opts.banner = 'Usage: joust <url> [options]'
|
25
|
+
|
26
|
+
opts.on('-o', '--only-check (v1.2|v2.0)', 'Check only against JSON-RPC Specifications for specified version') do |v|
|
27
|
+
options[:version] = v
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on_tail("-?", "--help", "Show this message") do
|
31
|
+
puts opts
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
end.parse!
|
36
|
+
|
37
|
+
# specification test cases
|
38
|
+
require 'yaml'
|
39
|
+
test_cases = YAML.load(File.open(File.join(File.dirname(__FILE__), '..', 'data', 'specifications.yml')))
|
40
|
+
|
41
|
+
# run the spec checking
|
42
|
+
Joust.run(url, options, test_cases)
|
@@ -0,0 +1,126 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
v2.0: # http://www.jsonrpc.org/spec.html
|
4
|
+
- "Positional parameters (1/2)":
|
5
|
+
- '{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1}'
|
6
|
+
- !ruby/object:YAML::Joust::Version20
|
7
|
+
expected: {result: 19, id: 1}
|
8
|
+
- "Positional parameters (2/2)":
|
9
|
+
- '{"jsonrpc": "2.0", "method": "subtract", "params": [23, 42], "id": 2}'
|
10
|
+
- !ruby/object:YAML::Joust::Version20
|
11
|
+
expected: {result: -19, id: 2}
|
12
|
+
- "Named parameters (1/2)":
|
13
|
+
- '{"jsonrpc": "2.0", "method": "subtract_named", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}'
|
14
|
+
- !ruby/object:YAML::Joust::Version20
|
15
|
+
expected: {result: 19, id: 3}
|
16
|
+
- "Named parameters (2/2)":
|
17
|
+
- '{"jsonrpc": "2.0", "method": "subtract_named", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}'
|
18
|
+
- !ruby/object:YAML::Joust::Version20
|
19
|
+
expected: {result: 19, id: 4}
|
20
|
+
- "Notification (1/2)":
|
21
|
+
- '{"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]}'
|
22
|
+
- !ruby/object:YAML::Joust::Version20
|
23
|
+
expected: {}
|
24
|
+
- "Notification (2/2)":
|
25
|
+
- '{"jsonrpc": "2.0", "method": "foobar"}'
|
26
|
+
- !ruby/object:YAML::Joust::Version20
|
27
|
+
expected: {}
|
28
|
+
- "Missing method":
|
29
|
+
- '{"jsonrpc": "2.0", "method": "notthere", "id": 5}'
|
30
|
+
- !ruby/object:YAML::Joust::Version20
|
31
|
+
expected: {error: {code: -32601, message: "Method not found."}, id: 5}
|
32
|
+
- "Invalid JSON":
|
33
|
+
- '{"jsonrpc": "2.0", "method": "foobar, "params": "bar", "baz]'
|
34
|
+
- !ruby/object:YAML::Joust::Version20
|
35
|
+
expected: {error: {code: -32700, message: "Parse error."}, id: ~}
|
36
|
+
- "Invalid JSON-RPC":
|
37
|
+
- '{"jsonrpc": "2.0", "method": 1, "params": "bar"}'
|
38
|
+
- !ruby/object:YAML::Joust::Version20
|
39
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
40
|
+
- "Invalid batch JSON":
|
41
|
+
- '[ {"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},{"jsonrpc": "2.0", "method" ]'
|
42
|
+
- !ruby/object:YAML::Joust::Version20
|
43
|
+
expected: {error: {code: -32700, message: "Parse error."}, id: ~}
|
44
|
+
- "Empty array":
|
45
|
+
- '[]'
|
46
|
+
- !ruby/object:YAML::Joust::Version20
|
47
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
48
|
+
- "Invalid batch JSON-RPC (1/2)":
|
49
|
+
- '[1]'
|
50
|
+
-
|
51
|
+
- !ruby/object:YAML::Joust::Version20
|
52
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
53
|
+
- "Invalid batch JSON-RPC (2/2)":
|
54
|
+
- '[1,2,3]'
|
55
|
+
-
|
56
|
+
- !ruby/object:YAML::Joust::Version20
|
57
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
58
|
+
- !ruby/object:YAML::Joust::Version20
|
59
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
60
|
+
- !ruby/object:YAML::Joust::Version20
|
61
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
62
|
+
- "Batch call":
|
63
|
+
- >- [{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": 1},
|
64
|
+
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
|
65
|
+
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": 2},
|
66
|
+
{"foo": "boo"},
|
67
|
+
{"jsonrpc": "2.0", "method": "notthere", "params": {"name": "myself"}, "id": 5},
|
68
|
+
{"jsonrpc": "2.0", "method": "get_data", "id": 9}]
|
69
|
+
-
|
70
|
+
- !ruby/object:YAML::Joust::Version20
|
71
|
+
expected: {result: 7, id: 1}
|
72
|
+
- !ruby/object:YAML::Joust::Version20
|
73
|
+
expected: {result: 19, id: 2}
|
74
|
+
- !ruby/object:YAML::Joust::Version20
|
75
|
+
expected: {error: {code: -32600, message: "Invalid Request."}, id: ~}
|
76
|
+
- !ruby/object:YAML::Joust::Version20
|
77
|
+
expected: {error: {code: -32601, message: "Method not found."}, id: 5}
|
78
|
+
- !ruby/object:YAML::Joust::Version20
|
79
|
+
expected: {result: ["hello", 5], id: 9}
|
80
|
+
- "Batch call (all notifications)":
|
81
|
+
- >- [{"jsonrpc": "2.0", "method": "notify_sum", "params": [1,2,4]},
|
82
|
+
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]}]
|
83
|
+
- !ruby/object:YAML::Joust::Version20
|
84
|
+
expected: {}
|
85
|
+
|
86
|
+
v1.2: # http://jsonrpc.org/historical/jsonrpc12_proposal.html#specification
|
87
|
+
- "Positional parameters (1/2)":
|
88
|
+
- '{"method": "subtract", "params": [42, 23], "id": 1}'
|
89
|
+
- !ruby/object:YAML::Joust::Version12
|
90
|
+
expected: {result: 19, error:~, id: 1}
|
91
|
+
- "Positional parameters (2/2)":
|
92
|
+
- '{"method": "subtract", "params": [23, 42], "id": 2}'
|
93
|
+
- !ruby/object:YAML::Joust::Version12
|
94
|
+
expected: {result: -19, error:~, id: 2}
|
95
|
+
- "Named parameters (1/2)":
|
96
|
+
- '{"method": "subtract_named", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}'
|
97
|
+
- !ruby/object:YAML::Joust::Version12
|
98
|
+
expected: {result: 19, error:~, id: 3}
|
99
|
+
- "Named parameters (2/2)":
|
100
|
+
- '{"method": "subtract_named", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}'
|
101
|
+
- !ruby/object:YAML::Joust::Version12
|
102
|
+
expected: {result: 19, error:~, id: 4}
|
103
|
+
- "Notification (1/2)":
|
104
|
+
- '{"method": "update", "params": [1,2,3,4,5], "id": null}'
|
105
|
+
- !ruby/object:YAML::Joust::Version12
|
106
|
+
expected: {}
|
107
|
+
- "Notification (2/2)":
|
108
|
+
- '{"method": "foobar", error:~, "id": null}'
|
109
|
+
- !ruby/object:YAML::Joust::Version12
|
110
|
+
expected: {}
|
111
|
+
- "Missing method":
|
112
|
+
- '{ "method": "notthere", "id": 5}'
|
113
|
+
- !ruby/object:YAML::Joust::Version12
|
114
|
+
expected: {result:~, error: {code: -32601, message: "Procedure not found."}, id: 5}
|
115
|
+
- "Invalid JSON":
|
116
|
+
- '{"method": "foobar, "params": "bar", "baz]'
|
117
|
+
- !ruby/object:YAML::Joust::Version12
|
118
|
+
expected: {result:~, error: {code: -32700, message: "Parse error."}, id: ~}
|
119
|
+
- "Invalid JSON-RPC (1/2)":
|
120
|
+
- '[1,2,3]'
|
121
|
+
- !ruby/object:YAML::Joust::Version12
|
122
|
+
expected: {result:~, error: {code: -32600, message: "Invalid JSON-RPC."}, id: ~}
|
123
|
+
- "Invalid JSON-RPC (2/2)":
|
124
|
+
- '{"method": 1, "params": "bar"}'
|
125
|
+
- !ruby/object:YAML::Joust::Version12
|
126
|
+
expected: {result:~, error: {code: -32600, message: "Invalid JSON-RPC."}, id: ~}
|
data/lib/joust.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
require File.join('joust','expected_response.rb')
|
4
|
+
require File.join('joust','expected_response','version_12.rb')
|
5
|
+
require File.join('joust','expected_response','version_20.rb')
|
6
|
+
|
7
|
+
class Joust
|
8
|
+
|
9
|
+
# run each version spec and return results
|
10
|
+
def self.run(url, options, test_cases)
|
11
|
+
specs = self.new(url, test_cases[options[:version]], options[:version])
|
12
|
+
puts specs.check
|
13
|
+
end
|
14
|
+
|
15
|
+
# initialize an instance to test a specific version
|
16
|
+
def initialize(url, test_cases, version)
|
17
|
+
@url, @test_cases, @version = url, test_cases, version
|
18
|
+
end
|
19
|
+
|
20
|
+
# run specification checks and return results
|
21
|
+
def check
|
22
|
+
num_tests = passed_tests = 0
|
23
|
+
results = @test_cases.map(&:flatten).inject([]) do |results, test|
|
24
|
+
test_name, sent, expected = test.first, test.last.first, test.last.last
|
25
|
+
resp = RestClient.post(@url, sent, :content_type => 'application/json')
|
26
|
+
num_tests += 1
|
27
|
+
json_hash = JSON.parse(resp.body) rescue {}
|
28
|
+
if expected.is_a?(Array)
|
29
|
+
pass = expected.inject(true) { |pass, exp| pass = false unless exp.match?(json_hash.shift); pass }
|
30
|
+
else
|
31
|
+
pass = expected.match?(json_hash)
|
32
|
+
end
|
33
|
+
if !!pass
|
34
|
+
passed_tests += 1
|
35
|
+
result_output = 'PASS'
|
36
|
+
else
|
37
|
+
result_output = 'FAIL: ' + resp.body
|
38
|
+
end
|
39
|
+
results << "#{@version} #{test_name} -- #{result_output}"
|
40
|
+
results
|
41
|
+
end
|
42
|
+
results << "JSON-RPC #{@version}: #{passed_tests}/#{num_tests} tests passed"
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Joust
|
2
|
+
class ExpectedResponse
|
3
|
+
|
4
|
+
def match?(json_hash)
|
5
|
+
['result', 'error', 'id'].each { |key| @expected[key] = :missing if !@expected.has_key?(key) }
|
6
|
+
if json_hash.empty?
|
7
|
+
return false unless @expected.values == [:missing, :missing, :missing]
|
8
|
+
return true
|
9
|
+
end
|
10
|
+
@expected.each do |key, val|
|
11
|
+
next if val == :missing && !json_hash.has_key?(key)
|
12
|
+
return false unless json_hash[key] == val
|
13
|
+
end
|
14
|
+
true
|
15
|
+
rescue Exception
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/spec/joust_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Joust do
|
4
|
+
|
5
|
+
describe '.run' do
|
6
|
+
context 'given a target url, options, and a test case file' do
|
7
|
+
it 'creates a new instance if joust and runs the tests' do
|
8
|
+
fake_joust = double('joust')
|
9
|
+
fake_joust.should_receive(:check)
|
10
|
+
Joust.should_receive(:new).and_return(fake_joust)
|
11
|
+
Joust.run('http://url', {:foo => :bar}, {:version => :foo})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#initialize' do
|
17
|
+
context 'given a target url, options, and a test case file' do
|
18
|
+
it 'creates a new instance of Joust' do
|
19
|
+
joust = Joust.new('http://url', {:foo => :bar}, {:version => :foo})
|
20
|
+
joust.should be_instance_of Joust
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#check' do
|
26
|
+
it 'runs the test cases' do
|
27
|
+
fake_resp = double('resp')
|
28
|
+
fake_resp.stub!(:body)
|
29
|
+
content_type = {:content_type => 'application/json'}
|
30
|
+
RestClient.should_receive(:post).with('url', 'sent', content_type).and_return(fake_resp)
|
31
|
+
fake_expected = double('expected')
|
32
|
+
fake_expected.should_receive(:is_a?).with(Array).and_return(false)
|
33
|
+
fake_expected.should_receive(:match?).with({}).and_return(true)
|
34
|
+
fake_test_cases = [{'test' => ['sent', fake_expected]}]
|
35
|
+
joust = Joust.new('url', fake_test_cases, 'v3.14')
|
36
|
+
results = joust.check
|
37
|
+
results.last.should == "JSON-RPC v3.14: 1/1 tests passed"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: joust
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- R. Scott Reis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-14 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email:
|
16
|
+
executables:
|
17
|
+
- joust
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.rdoc
|
21
|
+
files:
|
22
|
+
- LICENSE.txt
|
23
|
+
- README.rdoc
|
24
|
+
- Rakefile
|
25
|
+
- bin/joust
|
26
|
+
- data/specifications.yml
|
27
|
+
- lib/joust/expected_response.rb
|
28
|
+
- lib/joust/expected_response/version_12.rb
|
29
|
+
- lib/joust/expected_response/version_20.rb
|
30
|
+
- lib/joust.rb
|
31
|
+
- spec/spec_helper.rb
|
32
|
+
- spec/joust_spec.rb
|
33
|
+
homepage: https://github.com/EvilScott/joust
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options:
|
37
|
+
- -m
|
38
|
+
- README.rdoc
|
39
|
+
- -t
|
40
|
+
- Joust
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.18
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: JSON-RPC Server Specification Compatibility Testing
|
61
|
+
test_files:
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/joust_spec.rb
|