wabur 0.2.0d1 → 0.4.0d1
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.
- 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'
|