thin_service 0.0.1

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.
@@ -0,0 +1,18 @@
1
+ '#--
2
+ '# Copyright (c) 2006-2007 Luis Lavena, Multimedia systems
3
+ '#
4
+ '# This source code is released under the MIT License.
5
+ '# See MIT-LICENSE file for details
6
+ '#++
7
+
8
+ #include once "testly.bi"
9
+
10
+ '# the code in this module runs after all
11
+ '# the other modules have "registered" their suites.
12
+
13
+ '# evaluate the result from run_tests() to
14
+ '# return a error to the OS or not.
15
+ if (run_tests() = false) then
16
+ end 1
17
+ end if
18
+
@@ -0,0 +1,92 @@
1
+ '#--
2
+ '# Copyright (c) 2006-2007 Luis Lavena, Multimedia systems
3
+ '#
4
+ '# This source code is released under the MIT License.
5
+ '# See MIT-LICENSE file for details
6
+ '#++
7
+
8
+ '# this program mock a common process that will:
9
+ '# output some text to stdout
10
+ '# output some error messages to stderr
11
+ '# will wait until Ctrl-C is hit (only if commandline contains "wait")
12
+ '# or drop an error if commandline contains "error"
13
+
14
+ #include once "crt.bi"
15
+ #include once "windows.bi"
16
+
17
+ dim shared as any ptr control_signal, control_mutex
18
+ dim shared flagged as byte
19
+ dim shared result as integer
20
+
21
+ function slow_console_handler(byval dwCtrlType as DWORD) as BOOL
22
+ dim result as BOOL
23
+
24
+ if (dwCtrlType = CTRL_C_EVENT) then
25
+ fprintf(stdout, !"out: CTRL-C received\r\n")
26
+ mutexlock(control_mutex)
27
+ result = 1
28
+ flagged = 1
29
+ condsignal(control_signal)
30
+ mutexunlock(control_mutex)
31
+ elseif (dwCtrlType = CTRL_BREAK_EVENT) then
32
+ fprintf(stdout, !"out: CTRL-BREAK received\r\n")
33
+ mutexlock(control_mutex)
34
+ result = 1
35
+ flagged = 2
36
+ condsignal(control_signal)
37
+ mutexunlock(control_mutex)
38
+ end if
39
+
40
+ return result
41
+ end function
42
+
43
+ sub wait_for(byval flag_level as integer)
44
+ flagged = 0
45
+ '# set handler
46
+ if (SetConsoleCtrlHandler(@slow_console_handler, 1) = 0) then
47
+ fprintf(stderr, !"err: cannot set console handler\r\n")
48
+ end if
49
+ fprintf(stdout, !"out: waiting for keyboard signal\r\n")
50
+ mutexlock(control_mutex)
51
+ do until (flagged = flag_level)
52
+ condwait(control_signal, control_mutex)
53
+ loop
54
+ mutexunlock(control_mutex)
55
+ fprintf(stdout, !"out: got keyboard signal\r\n")
56
+ if (SetConsoleCtrlHandler(@slow_console_handler, 0) = 0) then
57
+ fprintf(stderr, !"err: cannot unset console handler\r\n")
58
+ end if
59
+ end sub
60
+
61
+ function main() as integer
62
+ fprintf(stdout, !"out: message\r\n")
63
+ fprintf(stderr, !"err: error\r\n")
64
+
65
+ select case lcase(command(1))
66
+ case "wait":
67
+ sleep
68
+ return 0
69
+
70
+ case "error":
71
+ '# terminate with error code
72
+ return 1
73
+
74
+ case "slow1":
75
+ wait_for(1)
76
+ return 10
77
+
78
+ case "slow2":
79
+ wait_for(2)
80
+ return 20
81
+ end select
82
+ end function
83
+
84
+ control_signal = condcreate()
85
+ control_mutex = mutexcreate()
86
+
87
+ result = main()
88
+
89
+ conddestroy(control_signal)
90
+ mutexdestroy(control_mutex)
91
+
92
+ end result
@@ -0,0 +1,402 @@
1
+ '#--
2
+ '# Copyright (c) 2006-2007 Luis Lavena, Multimedia systems
3
+ '#
4
+ '# This source code is released under the MIT License.
5
+ '# See MIT-LICENSE file for details
6
+ '#++
7
+
8
+ #include once "console_process.bi"
9
+ #include once "file.bi"
10
+ #include once "testly.bi"
11
+ #include once "test_helpers.bi"
12
+
13
+ namespace Suite_Test_Console_Process
14
+ '# test helpers
15
+ declare function process_cleanup() as boolean
16
+
17
+ dim shared child as ConsoleProcess ptr
18
+
19
+ sub before_all()
20
+ kill("out.log")
21
+ kill("err.log")
22
+ kill("both.log")
23
+ kill("both_slow.log")
24
+ kill("both_forced.log")
25
+ end sub
26
+
27
+ sub after_each()
28
+ process_cleanup()
29
+ end sub
30
+
31
+ sub test_process_create()
32
+ child = new ConsoleProcess()
33
+ assert_not_equal(0, child)
34
+ assert_equal("", child->filename)
35
+ assert_equal("", child->arguments)
36
+ assert_false(child->running)
37
+ delete child
38
+ end sub
39
+
40
+ sub test_process_create_args()
41
+ child = new ConsoleProcess("mock_process.exe", "some params")
42
+ assert_equal("mock_process.exe", child->filename)
43
+ assert_equal("some params", child->arguments)
44
+ delete child
45
+ end sub
46
+
47
+ sub test_properly_quoted_filename()
48
+ child = new ConsoleProcess("C:\path with spaces\my_executable.exe", "some params")
49
+ assert_not_equal(0, instr(child->filename, !"\""))
50
+ delete child
51
+ end sub
52
+
53
+ sub test_failed_unexistant_process()
54
+ child = new ConsoleProcess("no_valid_file.exe", "some params")
55
+ assert_false(child->start())
56
+ assert_equal(0, child->pid)
57
+ assert_false(child->running)
58
+ delete child
59
+ end sub
60
+
61
+ sub test_process_spawn_exit_code()
62
+ child = new ConsoleProcess("mock_process.exe", "error")
63
+
64
+ '# start() should return true since it started, no matter if was terminated
65
+ '# improperly
66
+ assert_true(child->start())
67
+ sleep 500
68
+
69
+ '# should not be running, but pid should be != than 0
70
+ assert_not_equal(0, child->pid)
71
+
72
+ '# we need to wait a bit prior asking for state
73
+ '# the process could be still running
74
+ assert_false(child->running)
75
+
76
+ '# get exit code, should be 1
77
+ assert_equal(1, child->exit_code)
78
+
79
+ delete child
80
+ end sub
81
+
82
+ sub test_redirected_output()
83
+ assert_false(fileexists("out.log"))
84
+ assert_false(fileexists("err.log"))
85
+
86
+ '# redirected output is used with logging files.
87
+ child = new ConsoleProcess("mock_process.exe")
88
+
89
+ '# redirect stdout
90
+ assert_true(child->redirect(ProcessStdOut, "out.log"))
91
+ assert_string_equal("out.log", child->redirected_stdout)
92
+
93
+ '# redirect stderr
94
+ assert_true(child->redirect(ProcessStdErr, "err.log"))
95
+ assert_string_equal("err.log", child->redirected_stderr)
96
+
97
+ '# start() will be true since process terminated nicely
98
+ assert_true(child->start())
99
+ sleep 500
100
+
101
+ '# running should be false
102
+ assert_false(child->running)
103
+
104
+ '# exit_code should be 0
105
+ assert_equal(0, child->exit_code)
106
+
107
+ delete child
108
+
109
+ '# now out.log and err.log must exist and content must be valid.
110
+ assert_true(fileexists("out.log"))
111
+ assert_string_equal("out: message", content_of_file("out.log"))
112
+
113
+ assert_true(fileexists("err.log"))
114
+ assert_string_equal("err: error", content_of_file("err.log"))
115
+
116
+ assert_equal(0, kill("out.log"))
117
+ assert_equal(0, kill("err.log"))
118
+ end sub
119
+
120
+ sub test_redirected_merged_output()
121
+ dim content as string
122
+
123
+ '# redirected output is used with logging files.
124
+ child = new ConsoleProcess("mock_process.exe")
125
+
126
+ '# redirect both stdout and stderr
127
+ child->redirect(ProcessStdBoth, "both.log")
128
+ assert_equal("both.log", child->redirected_stdout)
129
+ assert_equal("both.log", child->redirected_stderr)
130
+
131
+ '# start() will be true since process terminated nicely
132
+ assert_true(child->start())
133
+ sleep 500
134
+
135
+ '# running should be false
136
+ assert_false(child->running)
137
+
138
+ '# exit_code should be 0
139
+ assert_equal(0, child->exit_code)
140
+
141
+ delete child
142
+
143
+ '# file must exists
144
+ assert_true(fileexists("both.log"))
145
+
146
+ '# contents must match
147
+ content = content_of_file("both.log")
148
+
149
+ assert_not_equal(0, instr(content, "out: message"))
150
+ assert_not_equal(0, instr(content, "err: error"))
151
+
152
+ assert_equal(0, kill("both.log"))
153
+ end sub
154
+
155
+ sub test_redirected_output_append()
156
+ dim content as string
157
+
158
+ child = new ConsoleProcess("mock_process.exe")
159
+
160
+ '# redirect both stdout and stderr
161
+ child->redirect(ProcessStdBoth, "both.log")
162
+
163
+ '# start() will be true since process terminated nicely
164
+ assert_true(child->start())
165
+ sleep 500
166
+
167
+ content = content_of_file("both.log")
168
+
169
+ '# start() again
170
+ assert_true(child->start())
171
+ sleep 500
172
+
173
+ delete child
174
+
175
+ assert_not_equal(len(content), len(content_of_file("both.log")))
176
+
177
+ assert_equal(0, kill("both.log"))
178
+ end sub
179
+
180
+ sub test_process_terminate()
181
+ dim content as string
182
+
183
+ '# redirected output is used with logging files.
184
+ child = new ConsoleProcess("mock_process.exe", "wait")
185
+ child->redirect(ProcessStdBoth, "both.log")
186
+
187
+ '# start
188
+ assert_true(child->start())
189
+ sleep 500
190
+
191
+ '# validate if running
192
+ assert_true(child->running)
193
+
194
+ '# validate PID
195
+ assert_not_equal(0, child->pid)
196
+
197
+ '# now terminates it
198
+ assert_true(child->terminate())
199
+ sleep 500
200
+
201
+ assert_equal(9, child->exit_code)
202
+
203
+ '# it should be done
204
+ assert_false(child->running)
205
+
206
+ delete child
207
+
208
+ '# validate output
209
+ '# file must exists
210
+ assert_true(fileexists("both.log"))
211
+
212
+ '# contents must match
213
+ content = content_of_file("both.log")
214
+
215
+ assert_not_equal(0, instr(content, "out: message"))
216
+ assert_not_equal(0, instr(content, "err: error"))
217
+ assert_not_equal(0, instr(content, "interrupted"))
218
+
219
+ assert_equal(0, kill("both.log"))
220
+ end sub
221
+
222
+ sub test_process_terminate_slow1()
223
+ dim content as string
224
+
225
+ '# redirected output is used with logging files.
226
+ child = new ConsoleProcess("mock_process.exe", "slow1")
227
+ child->redirect(ProcessStdBoth, "both_slow1.log")
228
+
229
+ '# start
230
+ assert_true(child->start())
231
+ sleep 500
232
+
233
+ '# validate if running
234
+ assert_true(child->running)
235
+
236
+ '# validate PID
237
+ assert_not_equal(0, child->pid)
238
+
239
+ '# now terminates it
240
+ assert_true(child->terminate())
241
+ sleep 500
242
+
243
+ assert_equal(10, child->exit_code)
244
+
245
+ '# it should be done
246
+ assert_false(child->running)
247
+
248
+ delete child
249
+
250
+ '# validate output
251
+ '# file must exists
252
+ assert_true(fileexists("both_slow1.log"))
253
+
254
+ '# contents must match
255
+ content = content_of_file("both_slow1.log")
256
+
257
+ assert_equal(0, instr(content, "interrupted"))
258
+ assert_not_equal(0, instr(content, "out: CTRL-C received"))
259
+ assert_equal(0, instr(content, "out: CTRL-BREAK received"))
260
+
261
+ assert_equal(0, kill("both_slow1.log"))
262
+ end sub
263
+
264
+ sub test_process_terminate_slow2()
265
+ dim content as string
266
+
267
+ '# redirected output is used with logging files.
268
+ child = new ConsoleProcess("mock_process.exe", "slow2")
269
+ child->redirect(ProcessStdBoth, "both_slow2.log")
270
+
271
+ '# start
272
+ assert_true(child->start())
273
+ sleep 500
274
+
275
+ '# validate if running
276
+ assert_true(child->running)
277
+
278
+ '# validate PID
279
+ assert_not_equal(0, child->pid)
280
+
281
+ '# now terminates it
282
+ assert_true(child->terminate())
283
+ sleep 500
284
+
285
+ assert_equal(20, child->exit_code)
286
+
287
+ '# it should be done
288
+ assert_false(child->running)
289
+
290
+ delete child
291
+
292
+ '# validate output
293
+ '# file must exists
294
+ assert_true(fileexists("both_slow2.log"))
295
+
296
+ '# contents must match
297
+ content = content_of_file("both_slow2.log")
298
+
299
+ assert_equal(0, instr(content, "interrupted"))
300
+ assert_not_equal(0, instr(content, "out: CTRL-C received"))
301
+ assert_not_equal(0, instr(content, "out: CTRL-BREAK received"))
302
+
303
+ '# cleanup
304
+ assert_equal(0, kill("both_slow2.log"))
305
+ end sub
306
+
307
+ sub test_process_terminate_forced()
308
+ dim content as string
309
+
310
+ '# redirected output is used with logging files.
311
+ child = new ConsoleProcess("mock_process.exe", "wait")
312
+ child->redirect(ProcessStdBoth, "both_forced.log")
313
+
314
+ '# start
315
+ assert_true(child->start())
316
+ sleep 500
317
+
318
+ '# validate if running
319
+ assert_true(child->running)
320
+
321
+ '# validate PID
322
+ assert_not_equal(0, child->pid)
323
+
324
+ '# now terminates it
325
+ assert_true(child->terminate(true))
326
+ sleep 500
327
+
328
+ '# it should be done
329
+ assert_false(child->running)
330
+
331
+ '# look for termination code
332
+ assert_equal(0, child->exit_code)
333
+
334
+ delete child
335
+
336
+ '# validate output
337
+ '# file must exists
338
+ assert_true(fileexists("both_forced.log"))
339
+
340
+ '# contents must match
341
+ content = content_of_file("both_forced.log")
342
+
343
+ assert_equal(0, instr(content, "out: message"))
344
+ assert_equal(0, instr(content, "err: error"))
345
+ assert_equal(0, instr(content, "interrupted"))
346
+
347
+ assert_equal(0, kill("both_forced.log"))
348
+ end sub
349
+
350
+ sub test_reuse_object_instance()
351
+ dim first_pid as uinteger
352
+
353
+ child = new ConsoleProcess("mock_process.exe")
354
+
355
+ '# start
356
+ assert_true(child->start())
357
+ sleep 500
358
+
359
+ '# validate not running
360
+ assert_false(child->running)
361
+
362
+ '# validate PID
363
+ assert_not_equal(0, child->pid)
364
+
365
+ '# saves PID
366
+ first_pid = child->pid
367
+
368
+ '# start it again
369
+ assert_true(child->start())
370
+ sleep 500
371
+
372
+ '# it should have stopped by now
373
+ assert_false(child->running)
374
+ assert_not_equal(0, child->pid)
375
+ assert_not_equal(first_pid, child->pid)
376
+
377
+ delete child
378
+ end sub
379
+
380
+ private sub register() constructor
381
+ add_suite(Suite_Test_Console_Process)
382
+ add_test(test_process_create)
383
+ add_test(test_process_create_args)
384
+ add_test(test_properly_quoted_filename)
385
+ add_test(test_failed_unexistant_process)
386
+ add_test(test_process_spawn_exit_code)
387
+ add_test(test_redirected_output)
388
+ add_test(test_redirected_merged_output)
389
+ add_test(test_redirected_output_append)
390
+ add_test(test_process_terminate)
391
+ add_test(test_process_terminate_slow1)
392
+ add_test(test_process_terminate_slow2)
393
+ add_test(test_process_terminate_forced)
394
+ add_test(test_reuse_object_instance)
395
+ end sub
396
+
397
+ '# test helpers below this point
398
+ private function process_cleanup() as boolean
399
+ shell "taskkill /f /im mock_process.exe 1>NUL 2>&1"
400
+ return true
401
+ end function
402
+ end namespace