~drizzle-trunk/drizzle/development

2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
1
#! /usr/bin/env python
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
2
# -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
#
5
# Copyright (C) 2010 Patrick Crews
6
#
2121.3.2 by patrick crews
Updated license verbiage
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
2121.3.1 by patrick crews
Added licensing text to dbqp files
20
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
21
"""system_management.py
22
   code for dealing with system-level 'stuff'.
23
   This includes setting environment variables, looking for clients,
24
   so on and so forth.
25
26
   These things are / should be constant regardless of the testing being done
27
   We do an initial preflight / setup, we then call the mode-specific
28
   system_initialise() to do whatever the testing mode requires to do that
29
   voodoo that it do so well
30
31
"""
32
33
# imports
34
import os
35
import sys
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
36
import copy
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
37
from uuid import uuid4
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
38
import shutil
2124.2.1 by Patrick Crews
Updates to system_management.py to have better naming for symlinks in shm
39
import getpass
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
40
import commands
41
42
from lib.sys_mgmt.port_management import portManager
43
from lib.sys_mgmt.logging_management import loggingManager
2088.9.18 by patrick crews
Updates to allow for timing of test cases and reporting and whatnot
44
from lib.sys_mgmt.time_management import timeManager
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
45
46
class systemManager:
47
    """Class to deal with the basics of system-level interaction
48
       and awareness
49
50
       Uses other managers to handle sub-tasks like port management
51
52
    """
53
    def __init__(self, variables, tree_type='drizzle'):
54
        self.logging = loggingManager(variables)
55
        if variables['verbose']:
56
            self.logging.verbose("Initializing system manager...")
57
58
        self.skip_keys = [ 'code_tree'
2088.9.22 by patrick crews
Updated code to set LD_LIBRARY env vars
59
                         , 'ld_lib_paths'
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
60
                         , 'port_manager'
61
                         , 'logging_manager'
62
                         , 'environment_reqs'
63
                         , 'env_var_delimiter']
64
        self.debug = variables['debug']
65
        self.verbose = variables['verbose']
66
        self.env_var_delimiter = ':'
67
        self.no_shm = variables['noshm']
68
        self.shm_path = self.find_path(["/dev/shm", "/tmp"], required=0)
2121.5.1 by patrick crews
changes to parse netstat output better on freebsd for port management
69
        self.cur_os = os.uname()[0]
2124.2.1 by Patrick Crews
Updates to system_management.py to have better naming for symlinks in shm
70
        self.cur_user = getpass.getuser()
2124.2.6 by Patrick Crews
make target for dbqp! : )
71
        self.workdir = os.path.abspath(variables['workdir'])
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
72
        self.datadir = os.path.abspath(os.path.join(variables['testdir'],'dbqp_data'))
2124.2.6 by Patrick Crews
make target for dbqp! : )
73
        self.top_srcdir = os.path.abspath(variables['topsrcdir'])
74
        self.top_builddir = os.path.abspath(variables['topbuilddir'])
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
75
        self.start_dirty = variables['startdirty']
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
76
        self.valgrind = variables['valgrind']
2121.6.1 by patrick crews
Updates to allow for reorder option. Also added placeholder for --fast (it is one in test-run.pl as well), and a minor fix of output regarding libtool
77
        self.gdb = variables['gdb']
2158.2.1 by patrick crews
Added in --gdb and --manual-gdb option as well as --drizzled option
78
        self.manual_gdb = variables['manualgdb']
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
79
80
        # we use this to preface commands in order to run valgrind and such
81
        self.cmd_prefix = '' 
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
82
        
83
        self.port_manager = portManager(self,variables['debug'])
2088.9.18 by patrick crews
Updates to allow for timing of test cases and reporting and whatnot
84
        self.time_manager = timeManager(self)
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
85
                   
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
86
        # Make sure the tree we are testing looks good
87
        self.code_tree = self.get_code_tree(variables, tree_type)
88
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
89
        self.ld_lib_paths = self.join_env_var_values(self.code_tree.ld_lib_paths)
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
90
91
        # Some ENV vars are system-standard
92
        # We describe and set them here and now
93
        # The format is name: (value, append, suffix)
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
94
        self.environment_reqs = { 'UMASK':'0660'
95
                                , 'UMASK_DIR' : '0770'
96
                                , 'LC_ALL' : 'C'
97
                                , 'LC_CTYPE' : 'C'
98
                                , 'LC_COLLATE' : 'C'
99
                                , 'USE_RUNNING_SERVER' : "0"
100
                                , 'TOP_SRCDIR' : self.top_srcdir
101
                                , 'TOP_BUILDDIR' : self.top_builddir
102
                                , 'DRIZZLE_TEST_DIR' : self.code_tree.testdir
103
                                , 'DTR_BUILD_THREAD' : "-69.5"
104
                                , 'LD_LIBRARY_PATH' : self.append_env_var( 'LD_LIBRARY_PATH'
105
                                                                         , self.ld_lib_paths
106
                                                                         , suffix = 0
107
                                                                         , quiet = 1
108
                                                                         )
109
                                , 'DYLD_LIBRARY_PATH' : self.append_env_var( 'DYLD_LIBRARY_PATH'
110
                                                                         , self.ld_lib_paths
111
                                                                         , suffix = 0
112
                                                                         , quiet = 1
113
                                                                         )
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
114
                                }
115
        # set the env vars we need
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
116
        # self.process_environment_reqs(self.environment_reqs)
117
        self.update_environment_vars(self.environment_reqs)
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
118
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
119
        # We find or generate our id file
120
        # We use a uuid to identify the symlinked
121
        # workdirs.  That way, each installation
122
        # Will have a uuid/tmpfs workingdir
123
        # We store in a file so we know what
124
        # is ours
125
        self.uuid = self.get_uuid()
126
        self.symlink_name = 'dbqp_workdir_%s_%s' %(self.cur_user, self.uuid)
127
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
128
        # initialize our workdir
129
        self.process_workdir()
130
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
131
        # check for libtool
132
        self.libtool = self.libtool_check()
133
2158.2.1 by patrick crews
Added in --gdb and --manual-gdb option as well as --drizzled option
134
        # See if we need to do any further processing for special
135
        # options like valgrind and gdb
136
        self.handle_additional_reqs(variables)
137
     
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
138
        if self.debug:
139
            self.logging.debug_class(self)
140
        
141
    def get_code_tree(self, variables, tree_type):
142
        """Find out the important files, directories, and env. vars
143
           for a particular type of tree.  We import a definition module
144
           depending on the tree_type.  The module lets us know
145
           what to look for, etc
146
147
        """
148
        
149
        # Import the appropriate module that defines
150
        # where we find what we need depending on 
151
        # tree type
152
        test_tree = self.process_tree_type(tree_type, variables)
153
        return test_tree
154
155
    def process_tree_type(self, tree_type, variables):
156
        """Import the appropriate module depending on the type of tree
157
           we are testing. 
158
159
           Drizzle is the only supported type currently
160
161
        """
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
162
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
163
        if self.verbose:
164
            self.logging.verbose("Processing source tree under test...")
165
        if tree_type == 'drizzle':
166
            # base_case
167
            from lib.sys_mgmt.codeTree import drizzleTree
168
            test_tree = drizzleTree(variables,self)
169
            return test_tree
170
        else:
171
            self.logging.error("Tree_type: %s not supported yet" %(tree_type))
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
172
            sys.exit(1)        
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
173
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
174
    
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
175
    def create_dirset(self, rootdir, dirset):
176
        """ We produce the set of directories defined in dirset
177
            dirset is a set of dictionaries like
178
            {'dirname': 'subdir'}
179
            or {'dirname': {'subdir':'subsubdir}}...
180
181
            We generally expect there to be only a single
182
            top-level key.  The intent is to produce a dirset
183
            rooted at key[0], with various subdirs under that
184
            subsequest dirsets should be handles in separate calls...
185
186
        """
187
        for dirname in dirset.keys():
188
            full_path = os.path.join(rootdir, dirname)
189
            subdirset = dirset[dirname]
190
            if type(subdirset) is str:
191
                self.create_symlink(subdirset,full_path)
192
            else:
193
                self.create_dir(full_path)        
194
                # dirset[dirname] is a new dictionary
195
                if subdirset is None:
196
                    {}
197
                else:
198
                    self.create_dirset(full_path,subdirset)
199
200
        return full_path    
201
2151.8.1 by patrick crews
Updates to allow several dbqp's run run on one system (via uuid) and fix to return a relevant code post-execution (ie 1 if tests failed or timed out))
202
    def get_uuid(self):
203
        """ We look to see if a uuid file exists
204
            If so, we use that to know where to work
205
            If not we produce one so future runs
206
            have a definitive id to use
207
208
        """
209
210
        uuid_file_name = os.path.join(self.datadir, 'uuid')
211
        if os.path.exists(uuid_file_name):
212
            uuid_file = open(uuid_file_name,'r')
213
            uuid = uuid_file.readline().strip()
214
            uuid_file.close()
215
        else:
216
            uuid = uuid4()
217
            uuid_file = open(uuid_file_name,'w')
218
            uuid_file.write(str(uuid))
219
            uuid_file.close()
220
        return uuid
221
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
222
    def process_workdir(self):
223
        """ We create our workdir, analyze relevant variables
224
            to see if we should/shouldn't symlink to shm
225
            We do nothing if we have --start-dirty
226
227
        """
228
        
229
        if os.path.exists(self.workdir):
230
            # our workdir already exists
231
            if self.start_dirty:
232
                self.logging.info("Using --start-dirty, not attempting to touch directories")
233
                return
234
            else:
235
                self.remove_dir(self.workdir)
236
        self.allocate_workdir()
237
    
238
239
    def allocate_workdir(self):
240
        """ Create a workdir according to user-supplied specs """
241
        if self.no_shm:
242
            self.logging.info("Using --no-shm, will not link workdir to shm")
243
            self.create_dir(self.workdir, subdir=0)
244
        elif self.shm_path == None:
245
            self.logging.info("Could not find shared memory path for use.  Not linking workdir to shm")
246
            self.create_dir(self.workdir, subdir=0)
247
        else:
248
            shm_workdir = self.create_dir(os.path.join(self.shm_path, self.symlink_name))
249
            self.logging.info("Linking workdir %s to %s" %(self.workdir, shm_workdir))  
250
            self.create_symlink(shm_workdir, self.workdir)
251
252
    def create_dir(self, dirname, subdir =1 ):
253
        """ Create a directory.  If subdir = 1,
254
            then the new dir should be a subdir of
255
            self.workdir.  Else, we just create dirname,
256
            which should really be dirpath in this case
257
258
        """
259
260
        if subdir:
261
            full_path = os.path.join(self.workdir, dirname)
262
        else:
263
            full_path = dirname
264
265
        if os.path.exists(full_path):
266
            if self.start_dirty:
267
                return full_path
268
            else:
269
                shutil.rmtree(full_path)
270
            if self.debug:
271
                 self.logging.debug("Creating directory: %s" %(dirname))   
272
        os.makedirs(full_path)
273
        return full_path
274
275
    def remove_dir(self, dirname, require_empty=0 ):
276
        """ Remove the directory in question.
277
            We assume we want to brute-force clean
278
            things.  If require_empty = 0, then
279
            the dir must be empty to remove it
280
281
        """
282
        if self.debug:
283
            self.logging.debug("Removing directory: %s" %(dirname))
284
        if os.path.islink(dirname):
285
            os.remove(dirname)
286
        elif require_empty:
287
            os.rmdir(dirname)
288
        else:
289
            shutil.rmtree(dirname)
290
291
    def copy_dir(self, srcdir, tgtdir, overwrite = 1):
292
        """ Copy the contents of srcdir to tgtdir.
293
            We overwrite (remove/recreate) tgtdir
294
            if overwrite == 1
295
296
        """
297
        if self.debug:
298
            self.logging.debug("Copying directory: %s to %s" %(srcdir, tgtdir))
299
        if os.path.exists(tgtdir):
300
            if overwrite:
301
                self.remove_dir(tgtdir)
302
            else:
303
                self.logging.error("Cannot overwrite existing directory: %s" %(tgtdir))
304
                sys.exit(1)
305
        shutil.copytree(srcdir, tgtdir, symlinks=True)
306
307
    def create_symlink(self, source, link_name):
308
        """ We create a symlink to source named link_name """
309
        if self.debug:
310
            self.logging.debug("Creating symlink from %s to %s" %(source, link_name))
2088.9.10 by patrick crews
Updates to filesystem_engine and transaction_log tests to allow dbqp + test-run.pl to live together and execute all tests
311
        if os.path.exists(link_name) or os.path.islink(link_name):
312
            os.remove(link_name)
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
313
        return os.symlink(source, link_name)
314
2088.9.10 by patrick crews
Updates to filesystem_engine and transaction_log tests to allow dbqp + test-run.pl to live together and execute all tests
315
    def create_symlinks(self, needed_symlinks):
316
        """ We created the symlinks in needed_symlinks 
317
            We expect it to be tuples in source, link_name format
318
319
        """
320
        
321
        for needed_symlink in needed_symlinks:
322
            source, link_name = needed_symlink
323
            self.create_symlink(source, link_name)
324
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
325
    def join_env_var_values(self, value_list):
326
        """ Utility to join multiple values into a nice string
327
            for setting an env var to
328
 
329
        """
330
331
        return self.env_var_delimiter.join(value_list)
332
333
    def set_env_var(self, var_name, var_value, quiet=0):
334
        """Set an environment variable.  We really just abstract
335
           voodoo on os.environ
336
337
        """
338
        if self.debug and not quiet:
339
            self.logging.debug("Setting env var: %s" %(var_name))
340
        try:
341
            os.environ[var_name]=var_value
342
        except Exception, e:
343
            self.logging.error("Issue setting environment variable %s to value %s" %(var_name, var_value))
344
            self.logging.error("%s" %(e))
345
            sys.exit(1)
346
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
347
    def update_environment_vars(self, desired_vars, working_environment=None):
348
        """ We update the environment vars with desired_vars
349
            The expectation is that you know what you are asking for ; )
350
            If working_environment is provided, we will update that with
351
            desired_vars.  We operate directly on os.environ by default
352
            We return our updated environ dictionary
353
354
        """
355
356
        if not working_environment:
357
            working_environment = os.environ
358
        working_environment.update(desired_vars)
359
        return working_environment
360
361
    def create_working_environment(self, desired_vars):
362
        """ We return a copy of os.environ updated with desired_vars """
363
364
        working_copy = copy.deepcopy(os.environ)
365
        return self.update_environment_vars( desired_vars
366
                                    , working_environment = working_copy )
367
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
368
    def append_env_var(self, var_name, append_string, suffix=1, quiet=0):
369
        """ We add the values in var_values to the environment variable 
370
            var_name.  Depending on suffix value, we either append or prepend
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
371
            we return a string suitable for os.putenv
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
372
373
        """
374
        new_var_value = ""
375
        if var_name in os.environ:
376
            cur_var_value = os.environ[var_name]
377
            if suffix: # We add new values to end of existing value
378
                new_var_values = [ cur_var_value, append_string ]
379
            else:
380
                new_var_values = [ append_string, cur_var_value ]
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
381
            new_var_value = self.env_var_delimiter.join(new_var_values)
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
382
        else:
383
            # No existing variable value
384
            new_var_value = append_string
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
385
        return new_var_value
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
386
387
    def find_path(self, paths, required=1):
388
        """We search for the files we need / want to be aware of
389
           such as the drizzled binary, the various client binaries, etc
390
           We use the required switch to determine if we die or not
391
           if we can't find the file.
392
393
           We expect paths to be a list of paths, ordered in terms
394
           of preference (ie we want to use something from search-path1
395
           before search-path2).
396
397
           We return None if no match found and this wasn't required
398
399
        """
400
401
        for test_path in paths:
402
            if self.debug:
403
                self.logging.debug("Searching for path: %s" %(test_path))
404
            if os.path.exists(test_path):
405
                return test_path
406
        if required:
407
            self.logging.error("Required file not found out of options: %s" %(" ,".join(paths)))
408
            sys.exit(1)
409
        else:
410
            return None
411
412
    def execute_cmd(self, cmd, must_pass = 1):
413
        """ Utility function to execute a command and
414
            return the output and retcode
415
416
        """
417
418
        if self.debug:
419
            self.logging.debug("Executing command: %s" %(cmd))
420
        (retcode, output)= commands.getstatusoutput(cmd)
421
        if not retcode == 0 and must_pass:
422
            self.logging.error("Command %s failed with retcode %d" %(cmd, retcode))
423
            self.logging.error("%s" %(output))
424
            sys.exit(1)
425
        return retcode, output
426
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
427
    def libtool_check(self):
428
        """ We search for libtool """
429
        libtool_path = '../libtool'
430
        if os.path.exists(libtool_path) and os.access( libtool_path
431
                                                     , os.X_OK):
2121.6.1 by patrick crews
Updates to allow for reorder option. Also added placeholder for --fast (it is one in test-run.pl as well), and a minor fix of output regarding libtool
432
            if self.valgrind or self.gdb:
433
                self.logging.info("Using libtool when running valgrind or debugger")
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
434
            return libtool_path
435
        else:
436
            return None
437
2158.2.1 by patrick crews
Added in --gdb and --manual-gdb option as well as --drizzled option
438
    def handle_additional_reqs(self, variables):
439
        """ Do what we need to do to set things up for
440
            options like valgrind and gdb
441
442
        """
443
444
        # do we need to setup for valgrind?
445
        if self.valgrind:
446
            self.handle_valgrind_reqs(variables['valgrindarglist'])
447
448
    def handle_gdb_reqs(self, server, server_args):
449
        """ We generate the gdb init file and whatnot so we
450
            can run gdb properly
451
452
            if the user has specified manual-gdb, we provide
453
            them with a message about when to start and
454
            signal the server manager to simply wait
455
            for the server to be started by the user
456
457
        """
458
        extra_args = ''
459
        gdb_term_cmd = "xterm -title %s.%s " %( server.owner
460
                                              , server.name
461
                                              )
462
        gdb_file_name = "%s.gdbinit" %(server.name)
463
464
        if self.cur_os == 'Darwin': # Mac...ick ; P
465
            extra_args = [ "set env DYLD_INSERT_LIBRARIES /usr/lib/libgmalloc.dylib"
466
                         , "set env MallocStackLogging 1"
467
                         , "set env MallocScribble 1"
468
                         , "set env MallocPreScribble 1"
469
                         , "set env MallocStackLogging 1"
470
                         , "set env MallocStackLoggingNoCompact 1"
471
                         , "set env MallocGuardEdges 1"
472
                         ] 
473
474
        # produce our init file
475
        if extra_args:
476
            extra_args = "\n".join(extra_args)
477
        gdb_file_contents = [ "set args %s" %(" ".join(server_args))
478
                            , "%s" % (extra_args)
479
                            , "set breakpoint pending on"
480
	                          , "break drizzled::parse"
481
	                          , "commands 1"
482
                            , "disable 1"
483
	                          , "end"
484
                            , "set breakpoint pending off"
485
	                          , "run"
486
                            ]
487
        gdb_file_path = os.path.join(server.tmpdir, gdb_file_name)
488
        gdb_init_file = open(gdb_file_path,'w')
489
        gdb_init_file.write("\n".join(gdb_file_contents))
490
        gdb_init_file.close()
491
492
        # return our command line
493
        if self.libtool:
494
            libtool_string = "%s --mode=execute " %(self.libtool)
495
        else:
496
            libtool_string = ""
497
498
        if self.manual_gdb:
499
            self.logging.info("To start gdb, open another terminal and enter:")
500
            self.logging.info("%s/../libtool --mode=execute gdb -cd %s -x %s %s" %( self.code_tree.testdir
501
                                                                                  , self.code_tree.testdir
502
                                                                                  , gdb_file_path
503
                                                                                  , server.server_path
504
                                                                                  ) )
505
            return None
506
507
        else:
508
            return "%s -e %s gdb -x %s %s" %( gdb_term_cmd
509
                                            , libtool_string
510
                                            , gdb_file_path
511
                                            , server.server_path
512
                                            )
513
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
514
    def handle_valgrind_reqs(self, optional_args, mode='valgrind'):
515
        """ We do what voodoo we need to do to run valgrind """
516
        valgrind_args = [ "--show-reachable=yes"
2158.2.1 by patrick crews
Added in --gdb and --manual-gdb option as well as --drizzled option
517
                        , "--malloc-fill=22"
518
                        , "--free-fill=22"
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
519
                        # , "--trace-children=yes" this is for callgrind only
520
                        ]
521
        if optional_args:
522
        # we override the defaults with user-specified options
523
            valgrind_args = optional_args
524
        self.logging.info("Running valgrind with options: %s" %(" ".join(valgrind_args)))
525
526
        # set our environment variable
527
        self.set_env_var('VALGRIND_RUN', '1', quiet=0)
528
529
        # generate command prefix to call valgrind
530
        cmd_prefix = ''
531
        if self.libtool:
532
            cmd_prefix = "%s --mode=execute valgrind " %(self.libtool)
533
        if mode == 'valgrind':
534
            # default mode
535
536
            args = [ "--tool=memcheck"
537
                   , "--leak-check=yes"
538
                   , "--num-callers=16" 
539
                   ]
540
            # look for our suppressions file and add it to the mix if found
541
            suppress_file = os.path.join(self.code_tree.testdir,'valgrind.supp')
542
            if os.path.exists(suppress_file):
543
                args = args + [ "--suppressions=%s" %(suppress_file) ]
544
545
            cmd_prefix = cmd_prefix + " ".join(args + valgrind_args)
546
        self.cmd_prefix = cmd_prefix  
547
        
548
        # add debug libraries to ld_library_path
549
        debug_path = '/usr/lib/debug'
550
        if os.path.exists(debug_path):
551
            self.append_env_var("LD_LIBRARY_PATH", debug_path, suffix=1)
552
            self.append_env_var("DYLD_LIBRARY_PATH", debug_path, suffix=1)
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
553
554
   
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
555
    
556
557
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
558
 
559
        
560
        
561