forked from ctb/twill-legacy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
twill-fork
145 lines (111 loc) · 3.87 KB
/
twill-fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#! /usr/bin/env python
# This file is part of the twill source distribution.
#
# twill is a extensible scriptlet language for testing Web apps,
# available at http://twill.idyll.org/.
#
# Contact author: C. Titus Brown, titus@idyll.org.
#
# This program and all associated source code files are Copyright (C)
# 2005-2007 by C. Titus Brown. It is released under the MIT license;
# please see the included LICENSE.txt file for more information, or
# go to http://www.opensource.org/licenses/mit-license.php.
"""
twill multiprocess execution system.
"""
import sys, os, time
from twill import execute_file
from optparse import OptionParser
from cPickle import load, dump
###
# make sure that the current working directory is in the path. does this
# work on Windows??
if not '.' in sys.path:
sys.path.append('.')
###
#### OPTIONS
parser = OptionParser()
parser.add_option('-u', '--url', nargs=1, action="store", dest="url",
help="start at the given URL before each script")
parser.add_option('-n', '--number', nargs=1, action="store", dest="number",
default=1, type="int",
help="number of times to run the given script(s)")
parser.add_option('-p', '--processes', nargs=1, action="store",
dest="processes", default=1, type="int",
help="number of processes to execute in parallel")
####
# parse arguments.
(options, args) = parser.parse_args()
if not len(args):
sys.stderr.write('Error! Must specify one or more scripts to execute...\n')
sys.exit(-1)
average_number = int(options.number / options.processes)
last_number = average_number + options.number % options.processes
is_parent = True
child_pids = []
#
# start a bunch of child processes & record their pids in the parent.
#
for i in range(0, options.processes):
pid = os.fork()
if pid == 0:
if i == 0:
repeat = last_number # make sure we execute 'em *all*
else:
repeat = average_number
is_parent = False
break
else:
child_pids.append(pid) # keep track of children
#
# set the children up to run & record their stats
#
failed = False
if not is_parent:
print '[twill-fork: pid %d : executing %d times]' % (os.getpid(), repeat)
start_time = time.time()
for i in range(0, repeat):
for filename in args:
execute_file(filename, initial_url=options.url)
end_time = time.time()
this_time = end_time - start_time
# write statistics
fp = open('.status.%d' % (os.getpid(),), 'w')
info = (this_time, repeat)
dump(info, fp)
fp.close()
else: # is_parent
total_time = 0.
total_exec = 0
# iterate over all the child pids, wait 'til they finish, and then
# sum statistics.
left_childs = child_pids[:]
for child_pid in left_childs:
child_pid, status = os.waitpid(child_pid, 0)
# status != 0 indicates failure:
if status != 0:
print '[twill-fork parent: process %d FAILED: exit status %d]' % (child_pid, status,)
print '[twill-fork parent: (not counting stats for this process)]'
failed = True
else:
# record statistics, otherwise
fp = open('.status.%d' % (child_pid,))
(this_time, n_executed) = load(fp)
fp.close()
os.unlink('.status.%d' % (child_pid,))
total_time += this_time
total_exec += n_executed
#
# summarize
#
print '\n---'
print 'n processes: %d' % (options.processes,)
print 'total executed: %d' % (total_exec,)
print 'total time to execute: %f' % (total_time,)
if total_exec:
print 'average time: %f' % (total_time / total_exec,)
else:
print '(nothing completed, no average!)'
if failed:
sys.exit(-1)
sys.exit(0)