ruby-libvirt 0.2.0 → 0.3.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.
@@ -2,22 +2,110 @@
2
2
 
3
3
  # Test the nodedevice methods the bindings support
4
4
 
5
+ $: << File.dirname(__FILE__)
6
+
5
7
  require 'libvirt'
8
+ require 'test_utils.rb'
9
+
10
+ conn = Libvirt::open("qemu:///system")
11
+
12
+ # TESTGROUP: conn.num_of_nodedevices
13
+ expect_too_many_args(conn, "num_of_nodedevices", 1, 2, 3)
14
+ expect_invalid_arg_type(conn, "num_of_nodedevices", 1)
15
+ expect_invalid_arg_type(conn, "num_of_nodedevices", 'foo', 'bar')
16
+ expect_success(conn, "no args", "num_of_nodedevices")
17
+
18
+ # TESTGROUP: conn.list_nodedevices
19
+ expect_too_many_args(conn, "list_nodedevices", 1, 2, 3)
20
+ expect_invalid_arg_type(conn, "list_nodedevices", 1)
21
+ expect_invalid_arg_type(conn, "list_nodedevices", 'foo', 'bar')
22
+ expect_success(conn, "no args", "list_nodedevices")
23
+
24
+ # TESTGROUP: conn.lookup_nodedevice_by_name
25
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
26
+
27
+ expect_too_many_args(conn, "lookup_nodedevice_by_name", 1, 2)
28
+ expect_too_few_args(conn, "lookup_nodedevice_by_name")
29
+ expect_invalid_arg_type(conn, "lookup_nodedevice_by_name", 1)
30
+ expect_fail(conn, Libvirt::RetrieveError, "non-existent name arg", "lookup_nodedevice_by_name", "foobarbazsucker")
31
+
32
+ expect_success(conn, "name arg", "lookup_nodedevice_by_name", testnode.name)
33
+
34
+ # TESTGROUP: conn.create_nodedevice_xml
35
+ expect_too_many_args(conn, "create_nodedevice_xml", 1, 2, 3)
36
+ expect_too_few_args(conn, "create_nodedevice_xml")
37
+ expect_invalid_arg_type(conn, "create_nodedevice_xml", 1)
38
+ expect_invalid_arg_type(conn, "create_nodedevice_xml", "foo", 'bar')
39
+ expect_fail(conn, Libvirt::Error, "invalid XML", "create_nodedevice_xml", "hello")
40
+
41
+ #expect_success(conn, "nodedevice XML", "create_nodedevice_xml", "<nodedevice/>")
42
+
43
+ # TESTGROUP: nodedevice.name
44
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
45
+
46
+ expect_too_many_args(testnode, "name", 1)
47
+ expect_success(testnode, "no args", "name")
48
+
49
+ # TESTGROUP: nodedevice.parent
50
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
51
+
52
+ expect_too_many_args(testnode, "parent", 1)
53
+ expect_success(testnode, "no args", "parent")
54
+
55
+ # TESTGROUP: nodedevice.num_of_caps
56
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
57
+
58
+ expect_too_many_args(testnode, "num_of_caps", 1)
59
+ expect_success(testnode, "no args", "num_of_caps")
60
+
61
+ # TESTGROUP: nodedevice.list_caps
62
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
63
+
64
+ expect_too_many_args(testnode, "list_caps", 1)
65
+ expect_success(testnode, "no args", "list_caps")
6
66
 
7
- conn = Libvirt::open
8
- puts "Number of NodeDevices: #{conn.num_of_nodedevices}"
9
-
10
- conn.list_nodedevices.each do |nodename|
11
- nodedevice = conn.lookup_nodedevice_by_name(nodename)
12
- puts "NodeDevice #{nodedevice.name}:"
13
- puts " Parent: #{nodedevice.parent}"
14
- puts " Number Caps: #{nodedevice.num_of_caps}"
15
- puts " Caps:"
16
- nodedevice.list_caps.each do |cap|
17
- puts " #{cap}"
18
- end
19
- puts " XML:"
20
- puts nodedevice.xml_desc
21
- end
67
+ # TESTGROUP: nodedevice.xml_desc
68
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
69
+
70
+ expect_too_many_args(testnode, "xml_desc", 1, 2)
71
+ expect_invalid_arg_type(testnode, "xml_desc", 'foo')
72
+ expect_success(testnode, "no args", "xml_desc")
73
+
74
+ # TESTGROUP: nodedevice.detach
75
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
76
+
77
+ expect_too_many_args(testnode, "detach", 1)
78
+
79
+ #expect_success(testnode, "no args", "detach")
80
+
81
+ # TESTGROUP: nodedevice.reattach
82
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
83
+
84
+ expect_too_many_args(testnode, "reattach", 1)
85
+
86
+ #expect_success(testnode, "no args", "reattach")
87
+
88
+ # TESTGROUP: nodedevice.reset
89
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
90
+
91
+ expect_too_many_args(testnode, "reset", 1)
92
+
93
+ #expect_success(testnode, "no args", "reset")
94
+
95
+ # TESTGROUP: nodedevice.destroy
96
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
97
+
98
+ expect_too_many_args(testnode, "destroy", 1)
99
+
100
+ #expect_success(testnode, "no args", "destroy")
101
+
102
+ # TESTGROUP: nodedevice.free
103
+ testnode = conn.lookup_nodedevice_by_name(conn.list_nodedevices[0])
104
+
105
+ expect_too_many_args(testnode, "free", 1)
106
+
107
+ expect_success(testnode, "no args", "free")
22
108
 
23
109
  conn.close
110
+
111
+ finish_tests
@@ -2,27 +2,110 @@
2
2
 
3
3
  # Test the nwfilter methods the bindings support
4
4
 
5
+ $: << File.dirname(__FILE__)
6
+
5
7
  require 'libvirt'
8
+ require 'test_utils.rb'
9
+
10
+ UUID = "bd339530-134c-6d07-441a-17fb90dad807"
6
11
 
7
- conn = Libvirt::open
8
- puts "Number of NWFilters: #{conn.num_of_nwfilters}"
12
+ conn = Libvirt::open("qemu:///system")
9
13
 
10
14
  new_nwfilter_xml = <<EOF
11
- <filter name='no-spamming'>
12
- <uuid>d217f2d7-5a04-0e01-8b90-ec274a436b74</uuid>
15
+ <filter name='ruby-libvirt-tester' chain='ipv4'>
16
+ <uuid>#{UUID}</uuid>
17
+ <rule action='accept' direction='out' priority='100'>
18
+ <ip srcipaddr='0.0.0.0' dstipaddr='255.255.255.255' protocol='tcp' srcportstart='63000' dstportstart='62000'/>
19
+ </rule>
20
+ <rule action='accept' direction='in' priority='100'>
21
+ <ip protocol='tcp' srcportstart='63000' dstportstart='62000'/>
22
+ </rule>
13
23
  </filter>
14
24
  EOF
15
25
 
16
- newnwfilter = conn.define_nwfilter_xml(new_nwfilter_xml)
17
- newnwfilter.undefine
26
+ # TESTGROUP: conn.num_of_nwfilters
27
+ expect_too_many_args(conn, "num_of_nwfilters", 1)
28
+ expect_success(conn, "no args", "num_of_nwfilters")
29
+
30
+ # TESTGROUP: conn.list_nwfilters
31
+ expect_too_many_args(conn, "list_nwfilters", 1)
32
+ expect_success(conn, "no args", "list_nwfilters")
33
+
34
+ # TESTGROUP: conn.lookup_nwfilter_by_name
35
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
36
+
37
+ expect_too_many_args(conn, "lookup_nwfilter_by_name", 1, 2)
38
+ expect_too_few_args(conn, "lookup_nwfilter_by_name")
39
+ expect_invalid_arg_type(conn, "lookup_nwfilter_by_name", 1)
40
+
41
+ expect_success(conn, "name arg", "lookup_nwfilter_by_name", "ruby-libvirt-tester")
42
+
43
+ newnw.undefine
44
+
45
+ # TESTGROUP: conn.lookup_nwfilter_by_uuid
46
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
47
+
48
+ expect_too_many_args(conn, "lookup_nwfilter_by_uuid", 1, 2)
49
+ expect_too_few_args(conn, "lookup_nwfilter_by_uuid")
50
+ expect_invalid_arg_type(conn, "lookup_nwfilter_by_uuid", 1)
51
+
52
+ expect_success(conn, "uuid arg", "lookup_nwfilter_by_uuid", UUID) {|x| x.uuid == UUID}
53
+
54
+ newnw.undefine
55
+
56
+ # TESTGROUP: conn.define_nwfilter_xml
57
+ expect_too_many_args(conn, "define_nwfilter_xml", 1, 2)
58
+ expect_too_few_args(conn, "define_nwfilter_xml")
59
+ expect_invalid_arg_type(conn, "define_nwfilter_xml", 1)
60
+ expect_invalid_arg_type(conn, "define_nwfilter_xml", nil)
61
+ expect_fail(conn, Libvirt::DefinitionError, "invalid XML", "define_nwfilter_xml", "hello")
62
+
63
+ newnw = expect_success(conn, "nwfilter XML", "define_nwfilter_xml", new_nwfilter_xml)
64
+
65
+ newnw.undefine
66
+
67
+ # TESTGROUP: nwfilter.undefine
68
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
69
+
70
+ expect_too_many_args(newnw, "undefine", 1)
18
71
 
19
- conn.list_nwfilters.each do |nwfname|
20
- nwfilter = conn.lookup_nwfilter_by_name(nwfname)
21
- nwf2 = conn.lookup_nwfilter_by_uuid(nwfilter.uuid)
22
- puts "NWFilter #{nwfilter.name}:"
23
- puts " UUID: #{nwfilter.uuid}"
24
- puts " XML:"
25
- puts nwfilter.xml_desc
26
- end
72
+ expect_success(newnw, "no args", "undefine")
73
+
74
+ # TESTGROUP: nwfilter.name
75
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
76
+
77
+ expect_too_many_args(newnw, "name", 1)
78
+
79
+ expect_success(newnw, "no args", "name") {|x| x == "ruby-libvirt-tester"}
80
+
81
+ newnw.undefine
82
+
83
+ # TESTGROUP: nwfilter.uuid
84
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
85
+
86
+ expect_too_many_args(newnw, "uuid", 1)
87
+
88
+ expect_success(newnw, "no args", "uuid") {|x| x == UUID}
89
+
90
+ newnw.undefine
91
+
92
+ # TESTGROUP: nwfilter.xml_desc
93
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
94
+
95
+ expect_too_many_args(newnw, "xml_desc", 1, 2)
96
+ expect_invalid_arg_type(newnw, "xml_desc", "foo")
97
+
98
+ expect_success(newnw, "no args", "xml_desc")
99
+
100
+ newnw.undefine
101
+
102
+ # TESTGROUP: nwfilter.free
103
+ newnw = conn.define_nwfilter_xml(new_nwfilter_xml)
104
+ newnw.undefine
105
+ expect_too_many_args(newnw, "free", 1)
106
+
107
+ expect_success(newnw, "no args", "free")
27
108
 
28
109
  conn.close
110
+
111
+ finish_tests
@@ -2,22 +2,202 @@
2
2
 
3
3
  # Test the open calls that the bindings support
4
4
 
5
+ $: << File.dirname(__FILE__)
6
+
5
7
  require 'libvirt'
8
+ require 'test_utils.rb'
9
+
10
+ def expect_connect_error(func, args)
11
+ expect_fail(Libvirt, Libvirt::ConnectionError, "invalid driver", func, *args)
12
+ end
6
13
 
7
- conn = Libvirt::open
14
+ # TESTGROUP: Libvirt::version
15
+ expect_too_many_args(Libvirt, "version", "test", 1)
16
+ expect_invalid_arg_type(Libvirt, "version", 1)
17
+ expect_success(Libvirt, "no args", "version") {|x| x.class == Array and x.length == 2}
18
+ expect_success(Libvirt, "nil arg", "version", nil) {|x| x.class == Array and x.length == 2}
19
+ expect_success(Libvirt, "Test arg", "version", "Test") {|x| x.class == Array and x.length == 2}
20
+
21
+ # TESTGROUP: Libvirt::open
22
+ expect_too_many_args(Libvirt, "open", "qemu:///system", 1)
23
+ expect_connect_error("open", "foo:///system")
24
+ conn = expect_success(Libvirt, "no args", "open") {|x| x.class == Libvirt::Connect }
25
+ conn.close
26
+ conn = expect_success(Libvirt, "qemu:///system", "open", "qemu:///system") {|x| x.class == Libvirt::Connect }
27
+ conn.close
28
+ conn = expect_success(Libvirt, "nil arg", "open", nil) {|x| x.class == Libvirt::Connect }
8
29
  conn.close
9
30
 
10
- conn = Libvirt::open("qemu:///system")
31
+ # TESTGROUP: Libvirt::open_read_only
32
+ expect_too_many_args(Libvirt, "open_read_only", "qemu:///system", 1)
33
+ expect_connect_error("open_read_only", "foo:///system")
34
+ conn = expect_success(Libvirt, "no args", "open_read_only") {|x| x.class == Libvirt::Connect }
35
+ conn.close
36
+ conn = expect_success(Libvirt, "qemu:///system", "open_read_only", "qemu:///system") {|x| x.class == Libvirt::Connect }
37
+ conn.close
38
+ conn = expect_success(Libvirt, "nil arg", "open_read_only", nil) {|x| x.class == Libvirt::Connect }
39
+ conn.close
40
+
41
+ # TESTGROUP: Libvirt::open_auth
42
+ expect_too_many_args(Libvirt, "open_auth", "qemu:///system", [], "hello there", 1, 2)
43
+ expect_connect_error("open_auth", "foo:///system")
44
+ expect_invalid_arg_type(Libvirt, "open_auth", 1)
45
+ expect_invalid_arg_type(Libvirt, "open_auth", "qemu:///system", [], "hello", "foo")
46
+
47
+ conn = expect_success(Libvirt, "no args", "open_auth") {|x| x.class == Libvirt::Connect }
48
+ conn.close
49
+
50
+ conn = expect_success(Libvirt, "uri arg", "open_auth", "qemu:///system") {|x| x.class == Libvirt::Connect }
51
+ conn.close
52
+
53
+ conn = expect_success(Libvirt, "uri and empty cred args", "open_auth", "qemu:///system", []) {|x| x.class == Libvirt::Connect }
11
54
  conn.close
12
55
 
13
- conn = Libvirt::open(nil)
56
+ conn = expect_success(Libvirt, "uri and full cred args", "open_auth", "qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE]) {|x| x.class == Libvirt::Connect }
14
57
  conn.close
15
58
 
16
- conn = Libvirt::open_read_only
59
+ conn = expect_success(Libvirt, "uri, full cred, and user args", "open_auth", "qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], "hello") {|x| x.class == Libvirt::Connect }
17
60
  conn.close
18
61
 
19
- conn = Libvirt::open_read_only("qemu:///system")
62
+ # equivalent to "expect_success"
63
+ begin
64
+ conn = Libvirt::open_auth("qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], "hello") do |cred|
65
+ if not cred["userdata"].nil?
66
+ puts "userdata is #{cred["userdata"]}"
67
+ end
68
+ if cred["type"] == Libvirt::CRED_AUTHNAME
69
+ print "#{cred['prompt']}: "
70
+ res = gets
71
+ # strip off the \n
72
+ res = res[0..-2]
73
+ elsif cred["type"] == Libvirt::CRED_PASSPHRASE
74
+ print "#{cred['prompt']}: "
75
+ res = gets
76
+ res = res[0..-2]
77
+ else
78
+ raise "Unsupported credential #{cred['type']}"
79
+ end
80
+ res
81
+ end
82
+
83
+ puts "OK: open_auth uri, creds, userdata, auth block succeeded"
84
+ $SUCCESS = $SUCCESS + 1
85
+ conn.close
86
+ rescue NoMethodError
87
+ puts "SKIPPED: open_auth does not exist"
88
+ $SKIPPED = $SKIPPED + 1
89
+ rescue => e
90
+ puts "FAIL: open_auth uri, creds, userdata, auth block expected to succeed, threw #{e.class.to_s}: #{e.to_s}"
91
+ $FAIL = $FAIL + 1
92
+ end
93
+
94
+ # equivalent to "expect_success"
95
+ begin
96
+ conn = Libvirt::open_auth("qemu:///system", [Libvirt::CRED_AUTHNAME, Libvirt::CRED_PASSPHRASE], "hello", Libvirt::CONNECT_RO) do |cred|
97
+ if not cred["userdata"].nil?
98
+ puts "userdata is #{cred["userdata"]}"
99
+ end
100
+ if cred["type"] == Libvirt::CRED_AUTHNAME
101
+ print "#{cred['prompt']}: "
102
+ res = gets
103
+ # strip off the \n
104
+ res = res[0..-2]
105
+ elsif cred["type"] == Libvirt::CRED_PASSPHRASE
106
+ print "#{cred['prompt']}: "
107
+ res = gets
108
+ res = res[0..-2]
109
+ else
110
+ raise "Unsupported credential #{cred['type']}"
111
+ end
112
+ res
113
+ end
114
+
115
+ puts "OK: open_auth uri, creds, userdata, R/O flag, auth block succeeded"
116
+ $SUCCESS = $SUCCESS + 1
117
+ conn.close
118
+ rescue NoMethodError
119
+ puts "SKIPPED: open_auth does not exist"
120
+ $SKIPPED = $SKIPPED + 1
121
+ rescue => e
122
+ puts "FAIL: open_auth uri, creds, userdata, R/O flag, auth block expected to succeed, threw #{e.class.to_s}: #{e.to_s}"
123
+ $FAIL = $FAIL + 1
124
+ end
125
+
126
+ # TESTGROUP: Libvirt::event_register_impl
127
+ expect_too_many_args(Libvirt, "event_register_impl", 1, 2, 3, 4, 5, 6, 7)
128
+ expect_invalid_arg_type(Libvirt, "event_register_impl", 1)
129
+
130
+ # symbol callbacks
131
+ def virEventAddHandleImpl(fd, events, opaque)
132
+ end
133
+ def virEventUpdateHandleImpl(watch, event)
134
+ end
135
+ def virEventRemoveHandleImpl(handleID)
136
+ end
137
+ def virEventAddTimerImpl(interval, opaque)
138
+ end
139
+ def virEventUpdateTimerImpl(timer, timeout)
140
+ end
141
+ def virEventRemoveTimerImpl(timerID)
142
+ end
143
+
144
+ # proc callbacks
145
+ virEventAddHandleProc = lambda {|fd, events, opaque|
146
+ }
147
+ virEventUpdateHandleProc = lambda {|watch, event|
148
+ }
149
+ virEventRemoveHandleProc = lambda {|handleID|
150
+ }
151
+ virEventAddTimerProc = lambda {|interval, opaque|
152
+ }
153
+ virEventUpdateTimerProc = lambda {|timer, timeout|
154
+ }
155
+ virEventRemoveTimerProc = lambda {|timerID|
156
+ }
157
+
158
+ expect_success(Libvirt, "all Symbol callbacks", "event_register_impl", :virEventAddHandleImpl, :virEventUpdateHandleImpl, :virEventRemoveHandleImpl, :virEventAddTimerImpl, :virEventUpdateTimerImpl, :virEventRemoveTimerImpl)
159
+ expect_success(Libvirt, "unregister all callbacks", "event_register_impl", nil, nil, nil, nil, nil, nil)
160
+ expect_success(Libvirt, "all Proc callbacks", "event_register_impl", virEventAddHandleProc, virEventUpdateHandleProc, virEventRemoveHandleProc, virEventAddTimerProc, virEventUpdateTimerProc, virEventRemoveTimerProc)
161
+ expect_success(Libvirt, "unregister all callbacks", "event_register_impl")
162
+
163
+ # TESTGROUP: Libvirt::event_invoke_handle_callback
164
+ conn = Libvirt::open("qemu:///system")
165
+
166
+ expect_too_many_args(Libvirt, "event_invoke_handle_callback", 1, 2, 3, 4, 5)
167
+ expect_too_few_args(Libvirt, "event_invoke_handle_callback")
168
+ expect_too_few_args(Libvirt, "event_invoke_handle_callback", 1)
169
+ expect_too_few_args(Libvirt, "event_invoke_handle_callback", 1, 2)
170
+ expect_too_few_args(Libvirt, "event_invoke_handle_callback", 1, 2, 3)
171
+ # this is a bit bizarre; I am constructing a bogus hash to pass as the 4th
172
+ # parameter to event_invoke_handle_callback. In a real situation, I would
173
+ # have been given this hash from libvirt earlier, and just pass it on. I
174
+ # don't want all of that complexity here, though, so I create the bogus hash.
175
+ # One caveat; the data inside the hash *must* be of type T_DATA, so I pass in
176
+ # a fake conn object just to appease the type checker (so I can test out the
177
+ # other arguments properly)
178
+ expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", "hello", 1, 1, { "libvirt_cb" => conn, "opaque" => conn })
179
+ expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, "hello", 1, { "libvirt_cb" => conn, "opaque" => conn })
180
+ expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, 1, "hello", { "libvirt_cb" => conn, "opaque" => conn })
181
+ expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, 1, 1, { "libvirt_cb" => "hello", "opaque" => conn })
182
+ expect_invalid_arg_type(Libvirt, "event_invoke_handle_callback", 1, 1, 1, { "libvirt_cb" => conn, "opaque" => "hello" })
20
183
  conn.close
21
184
 
22
- conn = Libvirt::open_read_only(nil)
185
+ # TESTGROUP: Libvirt::event_invoke_timeout_callback
186
+ conn = Libvirt::open("qemu:///system")
187
+
188
+ expect_too_many_args(Libvirt, "event_invoke_timeout_callback", 1, 2, 3)
189
+ expect_too_few_args(Libvirt, "event_invoke_timeout_callback")
190
+ expect_too_few_args(Libvirt, "event_invoke_timeout_callback", 1)
191
+ # this is a bit bizarre; I am constructing a bogus hash to pass as the 4th
192
+ # parameter to event_invoke_handle_callback. In a real situation, I would
193
+ # have been given this hash from libvirt earlier, and just pass it on. I
194
+ # don't want all of that complexity here, though, so I create the bogus hash.
195
+ # One caveat; the data inside the hash *must* be of type T_DATA, so I pass in
196
+ # a fake conn object just to appease the type checker (so I can test out the
197
+ # other arguments properly)
198
+ expect_invalid_arg_type(Libvirt, "event_invoke_timeout_callback", "hello", { "libvirt_cb" => conn, "opaque" => conn })
199
+ expect_invalid_arg_type(Libvirt, "event_invoke_timeout_callback", 1, { "libvirt_cb" => "hello", "opaque" => conn })
200
+ expect_invalid_arg_type(Libvirt, "event_invoke_timeout_callback", 1, { "libvirt_cb" => conn, "opaque" => "hello" })
23
201
  conn.close
202
+
203
+ finish_tests