wabur 0.2.0d1 → 0.4.0d1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +40 -14
- data/bin/wabur +103 -0
- data/lib/wab/controller.rb +133 -90
- data/lib/wab/data.rb +14 -27
- data/lib/wab/errors.rb +14 -8
- data/lib/wab/impl/bool_expr.rb +25 -0
- data/lib/wab/impl/configuration.rb +166 -0
- data/lib/wab/impl/data.rb +155 -232
- data/lib/wab/impl/expr.rb +26 -0
- data/lib/wab/impl/expr_parser.rb +55 -0
- data/lib/wab/impl/exprs/and.rb +29 -0
- data/lib/wab/impl/exprs/between.rb +41 -0
- data/lib/wab/impl/exprs/eq.rb +28 -0
- data/lib/wab/impl/exprs/gt.rb +30 -0
- data/lib/wab/impl/exprs/gte.rb +30 -0
- data/lib/wab/impl/exprs/has.rb +26 -0
- data/lib/wab/impl/exprs/in.rb +28 -0
- data/lib/wab/impl/exprs/lt.rb +30 -0
- data/lib/wab/impl/exprs/lte.rb +30 -0
- data/lib/wab/impl/exprs/not.rb +27 -0
- data/lib/wab/impl/exprs/or.rb +29 -0
- data/lib/wab/impl/exprs/regex.rb +28 -0
- data/lib/wab/impl/handler.rb +95 -0
- data/lib/wab/impl/model.rb +197 -0
- data/lib/wab/impl/path_expr.rb +14 -0
- data/lib/wab/impl/shell.rb +92 -7
- data/lib/wab/impl/utils.rb +110 -0
- data/lib/wab/impl.rb +24 -0
- data/lib/wab/io/call.rb +4 -7
- data/lib/wab/io/engine.rb +128 -51
- data/lib/wab/io/shell.rb +61 -64
- data/lib/wab/io.rb +0 -2
- data/lib/wab/open_controller.rb +43 -0
- data/lib/wab/shell.rb +46 -61
- data/lib/wab/shell_logger.rb +13 -0
- data/lib/wab/utils.rb +36 -0
- data/lib/wab/uuid.rb +3 -6
- data/lib/wab/version.rb +2 -2
- data/lib/wab.rb +3 -0
- data/pages/Plan.md +20 -14
- data/test/bench_io_shell.rb +49 -0
- data/test/{impl_test.rb → helper.rb} +2 -4
- data/test/mirror_controller.rb +16 -0
- data/test/test_configuration.rb +38 -0
- data/test/test_data.rb +207 -0
- data/test/test_expr.rb +35 -0
- data/test/test_expr_and.rb +24 -0
- data/test/test_expr_between.rb +43 -0
- data/test/test_expr_eq.rb +24 -0
- data/test/test_expr_gt.rb +24 -0
- data/test/test_expr_gte.rb +24 -0
- data/test/test_expr_has.rb +19 -0
- data/test/test_expr_in.rb +24 -0
- data/test/test_expr_lt.rb +24 -0
- data/test/test_expr_lte.rb +24 -0
- data/test/test_expr_not.rb +22 -0
- data/test/test_expr_or.rb +24 -0
- data/test/test_expr_regex.rb +30 -0
- data/test/test_impl.rb +38 -0
- data/test/test_io_shell.rb +189 -0
- data/test/test_model.rb +31 -0
- data/test/test_runner.rb +177 -0
- data/test/tests.rb +3 -8
- metadata +91 -18
- data/lib/wab/model.rb +0 -136
- data/lib/wab/view.rb +0 -21
- data/test/data_test.rb +0 -253
- data/test/ioshell_test.rb +0 -461
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
class TestExprNot < TestImpl
|
7
|
+
|
8
|
+
def test_not_native
|
9
|
+
x = WAB::Impl::Not.new(WAB::Impl::Eq.new('num', 7))
|
10
|
+
assert_equal(['NOT', ['EQ', 'num', 7]], x.native, 'NOT native mismatch')
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_not
|
14
|
+
d = make_sample_data
|
15
|
+
x = WAB::Impl::Not.new(WAB::Impl::Eq.new('num', 8))
|
16
|
+
assert(x.eval(d), 'checking NOT match')
|
17
|
+
|
18
|
+
x = WAB::Impl::Not.new(WAB::Impl::Eq.new('num', 7))
|
19
|
+
refute(x.eval(d), 'checking NOT mismatch')
|
20
|
+
end
|
21
|
+
|
22
|
+
end # TestExprNot
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
class TestExprOr < TestImpl
|
7
|
+
|
8
|
+
def test_or_native
|
9
|
+
x = WAB::Impl::Or.new(WAB::Impl::Has.new('num'), WAB::Impl::Eq.new('num', 7))
|
10
|
+
assert_equal(['OR', ['HAS', 'num'], ['EQ', 'num', 7]], x.native, 'OR native mismatch')
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_or
|
14
|
+
d = make_sample_data
|
15
|
+
x = WAB::Impl::Or.new(WAB::Impl::Has.new('str'), WAB::Impl::Eq.new('num', 8))
|
16
|
+
assert(x.eval(d), 'checking OR match')
|
17
|
+
|
18
|
+
x = WAB::Impl::Or.new(WAB::Impl::Has.new('none'), WAB::Impl::Eq.new('num', 8))
|
19
|
+
refute(x.eval(d), 'checking OR mismatch')
|
20
|
+
end
|
21
|
+
|
22
|
+
# TBD tests with no args, with one, with more than 2, test using append_arg
|
23
|
+
|
24
|
+
end # TestExprOr
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
require 'wab'
|
7
|
+
require 'wab/impl'
|
8
|
+
|
9
|
+
class TestExprRegex < TestImpl
|
10
|
+
|
11
|
+
def test_regex_native
|
12
|
+
x = WAB::Impl::Regex.new('str', '^a *.')
|
13
|
+
assert_equal(['REGEX', 'str', '^a *.'], x.native, 'REGEX native mismatch')
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_regex_int
|
17
|
+
d = make_sample_data
|
18
|
+
x = WAB::Impl::Regex.new('str', '^a .*')
|
19
|
+
assert(x.eval(d), 'checking REGEX match with string arg')
|
20
|
+
|
21
|
+
x = WAB::Impl::Regex.new('str', '^x .*')
|
22
|
+
refute(x.eval(d), 'checking REGEX mismatch with string arg')
|
23
|
+
|
24
|
+
x = WAB::Impl::Regex.new('num', 8)
|
25
|
+
refute(x.eval(d), 'checking REGEX mismatch with an integer arg')
|
26
|
+
end
|
27
|
+
|
28
|
+
# TBD more tests for each type, Float, boolean, String, URI, UUID, Time, BigDecimal, nil
|
29
|
+
|
30
|
+
end # TestExprRegex
|
data/test/test_impl.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
require 'wab/impl'
|
7
|
+
|
8
|
+
class TestImpl < Minitest::Test
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@shell = WAB::Impl::Shell.new(
|
12
|
+
WAB::Impl::Configuration.new('',
|
13
|
+
'base' => File.join(__dir__, 'tmp')
|
14
|
+
)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_sample_data()
|
19
|
+
@shell.data({
|
20
|
+
boo: true,
|
21
|
+
n: nil,
|
22
|
+
num: 7,
|
23
|
+
float: 7.654,
|
24
|
+
str: 'a string',
|
25
|
+
t: Time.gm(2017, 1, 5, 15, 4, 33.123456789),
|
26
|
+
big: BigDecimal('63.21'),
|
27
|
+
uri: URI('http://opo.technology/sample'),
|
28
|
+
uuid: WAB::UUID.new('b0ca922d-372e-41f4-8fea-47d880188ba3'),
|
29
|
+
a: [],
|
30
|
+
h: {},
|
31
|
+
})
|
32
|
+
end
|
33
|
+
end # TestImpl
|
34
|
+
|
35
|
+
require 'test_configuration'
|
36
|
+
require 'test_data'
|
37
|
+
require 'test_expr'
|
38
|
+
require 'test_model'
|
@@ -0,0 +1,189 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
require 'wab/impl'
|
7
|
+
require 'wab/io'
|
8
|
+
require 'mirror_controller'
|
9
|
+
|
10
|
+
class TestIoShell < Minitest::Test
|
11
|
+
|
12
|
+
def test_default_controller
|
13
|
+
run_fork_test([
|
14
|
+
[{rid: 'rid-mirror', api: 1, body: {kind: 'sample', num: 7}},
|
15
|
+
{rid: 'rid-mirror', api: 2, body: {kind: 'sample', num: 7}}]
|
16
|
+
])
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_create
|
20
|
+
run_fork_test([
|
21
|
+
[{rid: 'rid-create', api: 1, body: {op: 'NEW', path: ['sample'], content: {kind: 'sample', num: 7}}},
|
22
|
+
{rid: '1', api: 3, body: { insert:{ kind: 'sample', num: 7}}}],
|
23
|
+
[{rid: '1', api: 4, body: {ref: 123, code: 0}},
|
24
|
+
{rid: 'rid-create', api: 2, body: { ref: 123, code: 0}}]
|
25
|
+
])
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_create_with_where
|
29
|
+
run_fork_test([
|
30
|
+
[{rid: 'rid-create-where', api: 1, body: {op: 'NEW', path: ['sample'], query: {id: 12345}, content: {kind: 'sample', id: 12345, num: 7}}},
|
31
|
+
{rid: '1', api: 3, body: {where: ['AND', ['EQ', 'kind', "'sample"],['EQ', 'id', 12345]], insert:{ kind: 'sample', id: 12345, num: 7}}}],
|
32
|
+
[{rid: '1', api: 4, body: {ref: 123, code: 0}},
|
33
|
+
{rid: 'rid-create-where', api: 2, body: { ref: 123, code: 0 }}]
|
34
|
+
])
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_create_error
|
38
|
+
run_fork_test([
|
39
|
+
[{rid: 'rid-create-error', api: 1, body: {op: 'NEW', path: ['sample'], content: {kind: 'sample', num: 7}}},
|
40
|
+
{rid: '1', api: 3, body: { insert:{ kind: 'sample', num: 7}}}],
|
41
|
+
[{rid: '1', api: 4, body: {ref: 123, code: -1, error: 'something went wrong'}},
|
42
|
+
{rid: 'rid-create-error', api: 2, body: { code: -1, error: 'WAB::Error: error on sample create. something went wrong'}}]
|
43
|
+
])
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_read_by_id
|
47
|
+
run_fork_test([
|
48
|
+
[{rid: 'rid-read-id', api: 1, body: {op: 'GET', path: ['sample', '12345']}},
|
49
|
+
{rid: '1', api: 3, body: {where: 12345, select: '$'}}],
|
50
|
+
[{rid: '1', api: 4, body: {code: 0, results:[{kind: 'sample', id: 12345, num: 7}]}},
|
51
|
+
{rid: 'rid-read-id', api: 2, body: { code: 0, results:[{ id: 12345, data: { kind: 'sample', id: 12345, num: 7}}]}}]
|
52
|
+
])
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_read_by_attrs
|
56
|
+
run_fork_test([
|
57
|
+
[{rid: 'rid-read-attrs', api: 1, body: {op: 'GET', path: ['sample'], query: {id: 12345}}},
|
58
|
+
{rid: '1', api: 3, body: {where: ['AND', ['EQ', 'kind', "'sample"], ['EQ', 'id', 12345]], select: {id: '$ref', data: '$' }}}],
|
59
|
+
[{rid: '1', api: 4, body: {code: 0, results: [{id: 12345, data: {kind: 'sample', id: 12345, num: 7}}]}},
|
60
|
+
{rid: 'rid-read-attrs', api: 2, body: {code: 0, results:[{id: 12345, data: {kind: 'sample', id: 12345, num: 7}}]}}]
|
61
|
+
])
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_read_list
|
65
|
+
run_fork_test([
|
66
|
+
[{rid: 'rid-read-list', api: 1, body: {op: 'GET', path: ['sample']}},
|
67
|
+
{rid: '1', api: 3, body: {where: ['EQ', 'kind', "'sample"], select: { id: '$ref', data: '$'}}}],
|
68
|
+
[{rid: '1', api: 4, body: {code: 0, results: [12345]}},
|
69
|
+
{rid: 'rid-read-list', api: 2, body: {code: 0, results:[12345]}}]
|
70
|
+
])
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_read_select
|
74
|
+
run_fork_test([
|
75
|
+
[{rid: 'rid-read-select', api: 1, body: {op: 'GET', path: ['sample', 'list'], query: { Age: 'num' }}},
|
76
|
+
{rid: '1', api: 3, body: {where: ['EQ', 'kind', "'sample"], select: { ref: '$ref', Age: 'num'}}}],
|
77
|
+
[{rid: '1', api: 4, body: {code: 0, results: [{ref: 12345, Age: 7 }]}},
|
78
|
+
{rid: 'rid-read-select', api: 2, body: {code: 0, results:[{ref: 12345, Age: 7 }]}}]
|
79
|
+
])
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_update_by_id
|
83
|
+
run_fork_test([
|
84
|
+
[{rid: 'rid-update-id', api: 1, body: {op: 'MOD', path: ['sample', '12345'], content: {kind: 'sample', id: 12345, num: 7}}},
|
85
|
+
{rid: '1', api: 3, body: {where: 12345, update: { kind: 'sample', id: 12345, num: 7}}}],
|
86
|
+
[{rid: '1', api: 4, body: {code: 0, updated: [12345]}},
|
87
|
+
{rid: 'rid-update-id', api: 2, body: { code: 0, updated: [12345]}}]
|
88
|
+
])
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_update_by_attrs
|
92
|
+
run_fork_test([
|
93
|
+
[{rid: 'rid-update-attrs', api: 1, body: {op: 'MOD', path: ['sample'], query: {id: 12345}, content: {kind: 'sample', id: 12345, num: 7}}},
|
94
|
+
{rid: '1', api: 3, body: {where: ['AND', ['EQ', 'kind', "'sample"],['EQ', 'id', 12345]], update: { kind: 'sample', id: 12345, num: 7}}}],
|
95
|
+
[{rid: '1', api: 4, body: {code: 0, updated: [12345]}},
|
96
|
+
{rid: 'rid-update-attrs', api: 2, body: { code: 0, updated: [12345]}}]
|
97
|
+
])
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_delete_by_id
|
101
|
+
run_fork_test([
|
102
|
+
[{rid: 'rid-delete-id', api: 1, body: {op: 'DEL', path: ['sample', '12345']}},
|
103
|
+
{rid: '1', api: 3, body: {where: 12345, delete: nil}}],
|
104
|
+
[{rid: '1', api: 4, body: {code: 0, deleted: [12345]}},
|
105
|
+
{rid: 'rid-delete-id', api: 2, body: { code: 0, deleted: [12345]}}]
|
106
|
+
])
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_delete_by_attrs
|
110
|
+
run_fork_test([
|
111
|
+
[{rid: 'rid-delete-attrs', api: 1, body: {op: 'DEL', path: ['sample'], query: {id: 12345}}},
|
112
|
+
{rid: '1', api: 3, body: {where: ['AND', ['EQ', 'kind', "'sample"],['EQ', 'id', 12345]], delete: nil}}],
|
113
|
+
[{rid: '1', api: 4, body: {code: 0, deleted: [12345]}},
|
114
|
+
{rid: 'rid-delete-attrs', api: 2, body: { code: 0, deleted: [12345]}}]
|
115
|
+
])
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_timeout
|
119
|
+
run_fork_test([
|
120
|
+
[{rid: 'rid-timeout', api: 1, body: {op: 'NEW', path: ['sample'], content: {kind: 'sample', num: 7}}},
|
121
|
+
{rid: '1', api: 3, body: { insert:{ kind: 'sample', num: 7}}}],
|
122
|
+
[nil,
|
123
|
+
{rid: 'rid-timeout', api: 2, body: { code: -1, error: 'WAB::Error: error on sample create. Timed out waiting for 1.'}}]
|
124
|
+
])
|
125
|
+
end
|
126
|
+
|
127
|
+
# Fork and create a shell in the child. For each pair in the script send the
|
128
|
+
# first message and wait for the second. Compare second for test success of
|
129
|
+
# failure.
|
130
|
+
def run_fork_test(script)
|
131
|
+
# Windows does not support fork
|
132
|
+
return if RbConfig::CONFIG['host_os'] =~ /(mingw|mswin)/
|
133
|
+
|
134
|
+
to_r, to_w = IO.pipe
|
135
|
+
from_r, from_w = IO.pipe
|
136
|
+
|
137
|
+
if fork.nil? # child
|
138
|
+
$stdin = to_r
|
139
|
+
to_w.close
|
140
|
+
$stdout = from_w
|
141
|
+
from_r.close
|
142
|
+
|
143
|
+
shell = WAB::IO::Shell.new(2, 'kind', 0)
|
144
|
+
shell.timeout = 0.5
|
145
|
+
shell.logger.level = Logger::WARN # change to Logger::INFO for debugging
|
146
|
+
shell.register_controller(nil, MirrorController.new(shell))
|
147
|
+
shell.start
|
148
|
+
|
149
|
+
Process.exit(0)
|
150
|
+
else
|
151
|
+
to_r.close
|
152
|
+
from_w.close
|
153
|
+
|
154
|
+
# Shell#data should be called instead but for this test a shell is not
|
155
|
+
# desired.
|
156
|
+
script.each { |pair|
|
157
|
+
unless pair[0].nil?
|
158
|
+
to_w.puts(WAB::Impl::Data.new(pair[0], false).json)
|
159
|
+
to_w.flush
|
160
|
+
end
|
161
|
+
|
162
|
+
reply = nil
|
163
|
+
Oj.strict_load(from_r, symbol_keys: true) { |msg| reply = msg; break }
|
164
|
+
|
165
|
+
# remove backtrace if an error
|
166
|
+
bt = nil
|
167
|
+
if !reply.nil? && !reply[:body].nil?
|
168
|
+
bt = reply[:body].delete(:backtrace)
|
169
|
+
end
|
170
|
+
begin
|
171
|
+
assert_equal(pair[1], reply)
|
172
|
+
rescue Exception => e
|
173
|
+
puts ''
|
174
|
+
puts bt
|
175
|
+
raise e
|
176
|
+
end
|
177
|
+
}
|
178
|
+
# On error the pipe may be closed from the child side so the write will
|
179
|
+
# fail. Thats okay as the write is only to tell the child to shutdown
|
180
|
+
# and it already has.
|
181
|
+
begin
|
182
|
+
to_w.puts(WAB::Impl::Data.new({ api: -2 }, false).json)
|
183
|
+
to_w.flush
|
184
|
+
rescue Exception
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
data/test/test_model.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
require 'wab/impl/model'
|
7
|
+
|
8
|
+
class TestModel < TestImpl
|
9
|
+
|
10
|
+
def test_model_create
|
11
|
+
# nil arg indicates don't save to disk
|
12
|
+
model = WAB::Impl::Model.new(nil)
|
13
|
+
tql = {
|
14
|
+
rid: 12345,
|
15
|
+
insert: {
|
16
|
+
kind: 'Person',
|
17
|
+
name: 'Peter',
|
18
|
+
age: 63
|
19
|
+
}
|
20
|
+
}
|
21
|
+
result = model.query(tql)
|
22
|
+
assert_equal(0, result[:code], 'expected a 0 result code')
|
23
|
+
assert_equal(12345, result[:rid], 'expected correct rid')
|
24
|
+
ref = result[:ref]
|
25
|
+
# get and verify object was stored.
|
26
|
+
obj = model.get(ref)
|
27
|
+
|
28
|
+
assert_equal({kind: 'Person', name: 'Peter', age: 63}, obj.native, 'obj get mismatch')
|
29
|
+
end
|
30
|
+
|
31
|
+
end # TestModel
|
data/test/test_runner.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
require 'net/http'
|
7
|
+
require 'oj'
|
8
|
+
|
9
|
+
require 'wab/impl'
|
10
|
+
require 'wab/io'
|
11
|
+
|
12
|
+
# -----------------------------------------------------------------------------
|
13
|
+
# This is to verify that WAB-Runners behave as expected.
|
14
|
+
#
|
15
|
+
# Requirements:
|
16
|
+
# - The Runner (e.g. OpO daemon) should be started with the MirrorController
|
17
|
+
# class.
|
18
|
+
# - The host and port must be the last argument on the command line when
|
19
|
+
# invoking the test.
|
20
|
+
#
|
21
|
+
# Example usage:
|
22
|
+
# runner_test.rb localhost:6363
|
23
|
+
# -----------------------------------------------------------------------------
|
24
|
+
|
25
|
+
raise ArgumentError, 'Host and port not supplied.' if ARGV.empty?
|
26
|
+
|
27
|
+
$host, $port = ARGV[-1].split(':')
|
28
|
+
$port = $port.to_i
|
29
|
+
|
30
|
+
class TestRunner < Minitest::Test
|
31
|
+
|
32
|
+
# The Runner or rather it's storage is stateful so all steps in the test
|
33
|
+
# must be made in order to keep the test self contained. Each step is a
|
34
|
+
# separate function though.
|
35
|
+
def test_runner_basics
|
36
|
+
http = Net::HTTP.new($host, $port)
|
37
|
+
|
38
|
+
# Delete all records to start with a clean database
|
39
|
+
clear_records(http)
|
40
|
+
ref = create_record(http)
|
41
|
+
read_record(http, ref)
|
42
|
+
list_records(http, ref)
|
43
|
+
|
44
|
+
ref = update_record(http, ref)
|
45
|
+
read_after_update(http, ref)
|
46
|
+
|
47
|
+
delete_record(http, ref)
|
48
|
+
read_after_delete(http, ref)
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear_records(http)
|
52
|
+
resp = http.send_request('DELETE', '/v1/Article')
|
53
|
+
# Response should be an OK with a JSON body.
|
54
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
55
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the reference of the created record.
|
59
|
+
def create_record(http)
|
60
|
+
json = %|{
|
61
|
+
"kind": "Article",
|
62
|
+
"title": "Sample",
|
63
|
+
"text": "Just some random text."
|
64
|
+
}|
|
65
|
+
resp = http.send_request('PUT', '/v1/Article', json, { 'Content-Type' => 'application/json' })
|
66
|
+
# Response should be an OK with a JSON body.
|
67
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
68
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
69
|
+
|
70
|
+
# Make sure the message has the correct fields and values.
|
71
|
+
assert_equal(0, reply[:code], 'create reply.code should be 0 meaning no error')
|
72
|
+
ref = reply[:ref]
|
73
|
+
refute_equal(nil, ref, 'create reply record reference can not be nil')
|
74
|
+
refute_equal(0, ref, 'create reply record reference can not be 0')
|
75
|
+
ref
|
76
|
+
end
|
77
|
+
|
78
|
+
def read_record(http, ref)
|
79
|
+
resp = http.send_request('GET', "/v1/Article/#{ref}")
|
80
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
81
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
82
|
+
|
83
|
+
# Make sure the message has the correct fields and values.
|
84
|
+
assert_equal(0, reply[:code], 'read reply.code should be 0 meaning no error')
|
85
|
+
results = reply[:results]
|
86
|
+
assert_equal(1, results.length, 'read reply.results should contain exactly one member')
|
87
|
+
record = results[0]
|
88
|
+
assert_equal(ref, record[:id], 'read reply.results[0].id should match the record reference')
|
89
|
+
obj = record[:data]
|
90
|
+
assert_equal('Article', obj[:kind], 'read reply obj.kind incorrect')
|
91
|
+
assert_equal('Sample', obj[:title], 'read reply obj.title incorrect')
|
92
|
+
end
|
93
|
+
|
94
|
+
def list_records(http, ref)
|
95
|
+
resp = http.send_request('GET', '/v1/Article')
|
96
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
97
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
98
|
+
|
99
|
+
# Make sure the message has the correct fields and values.
|
100
|
+
assert_equal(0, reply[:code], 'read reply.code should be 0 meaning no error')
|
101
|
+
results = reply[:results]
|
102
|
+
assert_equal(1, results.length, 'read reply.results should contain exactly one member')
|
103
|
+
record = results[0]
|
104
|
+
assert_equal(ref, record[:id], 'read reply.results[0].id should match the record reference')
|
105
|
+
obj = record[:data]
|
106
|
+
assert_equal('Article', obj[:kind], 'read reply obj.kind incorrect')
|
107
|
+
assert_equal('Sample', obj[:title], 'read reply obj.title incorrect')
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns the reference of the updated record. There is no requirement that
|
111
|
+
# the reference will not change.
|
112
|
+
def update_record(http, ref)
|
113
|
+
json = %|{
|
114
|
+
"kind": "Article",
|
115
|
+
"title": "Sample",
|
116
|
+
"text": "Updated text."
|
117
|
+
}|
|
118
|
+
resp = http.send_request('POST', "/v1/Article/#{ref}", json, { 'Content-Type' => 'application/json' })
|
119
|
+
# Response should be an OK with a JSON body.
|
120
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
121
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
122
|
+
|
123
|
+
# Make sure the message has the correct fields and values.
|
124
|
+
assert_equal(0, reply[:code], 'update reply.code should be 0 meaning no error')
|
125
|
+
updated = reply[:updated]
|
126
|
+
assert_equal(1, updated.length, 'update reply.updated should contain exactly one member')
|
127
|
+
ref = updated[0]
|
128
|
+
refute_equal(nil, ref, 'update reply record reference can not be nil')
|
129
|
+
refute_equal(0, ref, 'update reply record reference can not be 0')
|
130
|
+
ref
|
131
|
+
end
|
132
|
+
|
133
|
+
def read_after_update(http, ref)
|
134
|
+
resp = http.send_request('GET', "/v1/Article/#{ref}")
|
135
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
136
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
137
|
+
|
138
|
+
assert_equal(0, reply[:code], 'read after update reply.code should be 0 meaning no error')
|
139
|
+
results = reply[:results]
|
140
|
+
assert_equal(1, results.length, 'read after update reply.results should contain exactly one member')
|
141
|
+
record = results[0]
|
142
|
+
assert_equal(ref, record[:id], 'read after update reply.results[0].id should match the record reference')
|
143
|
+
obj = record[:data]
|
144
|
+
assert_equal('Updated text.', obj[:text], 'read after update reply obj.text incorrect')
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete_record(http, ref)
|
148
|
+
resp = http.send_request('DELETE', "/v1/Article/#{ref}")
|
149
|
+
# Response should be an OK with a JSON body.
|
150
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
151
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
152
|
+
|
153
|
+
# Make sure the message has the correct fields and values.
|
154
|
+
assert_equal(0, reply[:code], 'delete reply.code should be 0 meaning no error')
|
155
|
+
deleted = reply[:deleted]
|
156
|
+
assert_equal(1, deleted.length, 'delete reply.deleted should contain exactly one member')
|
157
|
+
ref = deleted[0]
|
158
|
+
refute_equal(nil, ref, 'delete reply record reference can not be nil')
|
159
|
+
refute_equal(0, ref, 'delete reply record reference can not be 0')
|
160
|
+
end
|
161
|
+
|
162
|
+
def read_after_delete(http, ref)
|
163
|
+
resp = http.send_request('GET', "/v1/Article/#{ref}")
|
164
|
+
assert_equal(Net::HTTPOK, resp.class, 'response not an OK')
|
165
|
+
reply = Oj.strict_load(resp.body, symbol_keys: true)
|
166
|
+
|
167
|
+
assert_equal(0, reply[:code], 'read after delete reply.code should be 0 meaning no error')
|
168
|
+
results = reply[:results]
|
169
|
+
assert_equal(0, results.length, 'read after delete reply.results should contain no members')
|
170
|
+
end
|
171
|
+
|
172
|
+
# TBD test failure modes as well
|
173
|
+
# TBD test multiple matches on update and delete
|
174
|
+
# TBD test no matches on update and delete
|
175
|
+
# TBD test queries
|
176
|
+
|
177
|
+
end # TestRunner
|
data/test/tests.rb
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: UTF-8
|
3
3
|
|
4
|
-
|
5
|
-
$: << File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'lib')
|
4
|
+
require_relative 'helper'
|
6
5
|
|
7
|
-
require '
|
8
|
-
require '
|
9
|
-
|
10
|
-
require 'impl_test'
|
11
|
-
|
12
|
-
require 'ioshell_test'
|
6
|
+
require 'test_impl'
|
7
|
+
require 'test_io_shell'
|