import unittest import builtins import os from platform import system as platform_system class ExceptionClassTests(unittest.TestCase): """Tests for anything relating to exception objects themselves (e.g., inheritance hierarchy)""" def test_builtins_new_style(self): self.assertTrue(issubclass(Exception, object)) def verify_instance_interface(self, ins): for attr in ("args", "__str__", "__repr__"): self.assertTrue(hasattr(ins, attr), "%s missing %s attribute" % (ins.__class__.__name__, attr)) def test_inheritance(self): # Make sure the inheritance hierarchy matches the documentation exc_set = set() for object_ in builtins.__dict__.values(): try: if issubclass(object_, BaseException): exc_set.add(object_.__name__) except TypeError: pass inheritance_tree = open( os.path.join(os.path.split(__file__)[0], 'exception_hierarchy.txt'), encoding="utf-8") try: superclass_name = inheritance_tree.readline().rstrip() try: last_exc = getattr(builtins, superclass_name) except AttributeError: self.fail("base class %s not a built-in" % superclass_name) self.assertIn(superclass_name, exc_set, '%s not found' % superclass_name) exc_set.discard(superclass_name) superclasses = [] # Loop will insert base exception last_depth = 0 for exc_line in inheritance_tree: exc_line = exc_line.rstrip() depth = exc_line.rindex('-') exc_name = exc_line[depth+2:] # Slice past space if '(' in exc_name: paren_index = exc_name.index('(') platform_name = exc_name[paren_index+1:-1] exc_name = exc_name[:paren_index-1] # Slice off space if platform_system() != platform_name: exc_set.discard(exc_name) continue if '[' in exc_name: left_bracket = exc_name.index('[') exc_name = exc_name[:left_bracket-1] # cover space try: exc = getattr(builtins, exc_name) except AttributeError: self.fail("%s not a built-in exception" % exc_name) if last_depth < depth: superclasses.append((last_depth, last_exc)) elif last_depth > depth: while superclasses[-1][0] >= depth: superclasses.pop() self.assertTrue(issubclass(exc, superclasses[-1][1]), "%s is not a subclass of %s" % (exc.__name__, superclasses[-1][1].__name__)) try: # Some exceptions require arguments; just skip them self.verify_instance_interface(exc()) except TypeError: pass self.assertIn(exc_name, exc_set) exc_set.discard(exc_name) last_exc = exc last_depth = depth finally: inheritance_tree.close() self.assertEqual(len(exc_set), 0, "%s not accounted for" % exc_set) interface_tests = ("length", "args", "str", "repr") def interface_test_driver(self, results): for test_name, (given, expected) in zip(self.interface_tests, results): self.assertEqual(given, expected, "%s: %s != %s" % (test_name, given, expected)) def test_interface_single_arg(self): # Make sure interface works properly when given a single argument arg = "spam" exc = Exception(arg) results = ([len(exc.args), 1], [exc.args[0], arg], [str(exc), str(arg)], [repr(exc), '%s(%r)' % (exc.__class__.__name__, arg)]) self.interface_test_driver(results) def test_interface_multi_arg(self): # Make sure interface correct when multiple arguments given arg_count = 3 args = tuple(range(arg_count)) exc = Exception(*args) results = ([len(exc.args), arg_count], [exc.args, args], [str(exc), str(args)], [repr(exc), exc.__class__.__name__ + repr(exc.args)]) self.interface_test_driver(results) def test_interface_no_arg(self): # Make sure that with no args that interface is correct exc = Exception() results = ([len(exc.args), 0], [exc.args, tuple()], [str(exc), ''], [repr(exc), exc.__class__.__name__ + '()']) self.interface_test_driver(results) def test_setstate_refcount_no_crash(self): # gh-97591: Acquire strong reference before calling tp_hash slot # in PyObject_SetAttr. import gc d = {} class HashThisKeyWillClearTheDict(str): def __hash__(self) -> int: d.clear() return super().__hash__() class Value(str): pass exc = Exception() d[HashThisKeyWillClearTheDict()] = Value() # refcount of Value() is 1 now # Exception.__setstate__ should aquire a strong reference of key and # value in the dict. Otherwise, Value()'s refcount would go below # zero in the tp_hash call in PyObject_SetAttr(), and it would cause # crash in GC. exc.__setstate__(d) # __hash__() is called again here, clearing the dict. # This GC would crash if the refcount of Value() goes below zero. gc.collect() class UsageTests(unittest.TestCase): """Test usage of exceptions""" def raise_fails(self, object_): """Make sure that raising 'object_' triggers a TypeError.""" try: raise object_ except TypeError: return # What is expected. self.fail("TypeError expected for raising %s" % type(object_)) def catch_fails(self, object_): """Catching 'object_' should raise a TypeError.""" try: try: raise Exception except object_: pass except TypeError: pass except Exception: self.fail("TypeError expected when catching %s" % type(object_)) try: try: raise Exception except (object_,): pass except TypeError: return except Exception: self.fail("TypeError expected when catching %s as specified in a " "tuple" % type(object_)) def test_raise_new_style_non_exception(self): # You cannot raise a new-style class that does not inherit from # BaseException; the ability was not possible until BaseException's # introduction so no need to support new-style objects that do not # inherit from it. class NewStyleClass(object): pass self.raise_fails(NewStyleClass) self.raise_fails(NewStyleClass()) def test_raise_string(self): # Raising a string raises TypeError. self.raise_fails("spam") def test_catch_non_BaseException(self): # Trying to catch an object that does not inherit from BaseException # is not allowed. class NonBaseException(object): pass self.catch_fails(NonBaseException) self.catch_fails(NonBaseException()) def test_catch_BaseException_instance(self): # Catching an instance of a BaseException subclass won't work. self.catch_fails(BaseException()) def test_catch_string(self): # Catching a string is bad. self.catch_fails("spam") if __name__ == '__main__': unittest.main() Tcl is a high-level, general-purpose, interpreted, dynamic programming language. It was designed with the goal of being very simple but powerful.
summaryrefslogtreecommitdiffstats
path: root/generic/tclDTrace.d
blob: a2233b1aa69c6bb7818d4fa1021f91dba3a4fe53 (plain)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * tclDTrace.d --
 *
 *	Tcl DTrace provider.
 *
 * Copyright (c) 2007-2008 Daniel A. Steffen <das@users.sourceforge.net>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

typedef struct Tcl_Obj Tcl_Obj;

typedef ptrdiff_t Tcl_Size;

/*
 * Tcl DTrace probes
 */

provider tcl {
    /***************************** proc probes *****************************/
    /*
     *	tcl*:::proc-entry probe
     *	    triggered immediately before proc bytecode execution
     *		arg0: proc name				(string)
     *		arg1: number of arguments		(Tcl_Size)
     *		arg2: array of proc argument objects	(Tcl_Obj**)
     */
    probe proc__entry(const char *name, Tcl_Size objc, struct Tcl_Obj **objv);
    /*
     *	tcl*:::proc-return probe
     *	    triggered immediately after proc bytecode execution
     *		arg0: proc name				(string)
     *		arg1: return code			(int)
     */
    probe proc__return(const char *name, int code);
    /*
     *	tcl*:::proc-result probe
     *	    triggered after proc-return probe and result processing
     *		arg0: proc name				(string)
     *		arg1: return code			(int)
     *		arg2: proc result			(string)
     *		arg3: proc result object		(Tcl_Obj*)
     */
    probe proc__result(const char *name, int code, const char *result,
	    struct Tcl_Obj *resultobj);
    /*
     *	tcl*:::proc-args probe
     *	    triggered before proc-entry probe, gives access to string
     *	    representation of proc arguments
     *		arg0: proc name				(string)
     *		arg1-arg9: proc arguments or NULL	(strings)
     */
    probe proc__args(const char *name, const char *arg1, const char *arg2,
	    const char *arg3, const char *arg4, const char *arg5,
	    const char *arg6, const char *arg7, const char *arg8,
	    const char *arg9);
    /*
     *	tcl*:::proc-info probe
     *	    triggered before proc-entry probe, gives access to TIP 280
     *	    information for the proc invocation (i.e. [info frame 0])
     *		arg0: TIP 280 cmd			(string)
     *		arg1: TIP 280 type			(string)
     *		arg2: TIP 280 proc			(string)
     *		arg3: TIP 280 file			(string)
     *		arg4: TIP 280 line			(int)
     *		arg5: TIP 280 level			(Tcl_Size)
     *		arg6: TclOO method			(string)
     *		arg7: TclOO class/object		(string)
     */
    probe proc__info(const char *cmd, const char *type, const char *proc,
	    const char *file, int line, Tcl_Size level, const char *method,
	    const char *class);

    /***************************** cmd probes ******************************/
    /*
     *	tcl*:::cmd-entry probe
     *	    triggered immediately before commmand execution
     *		arg0: command name			(string)
     *		arg1: number of arguments		(Tcl_Size)
     *		arg2: array of command argument objects	(Tcl_Obj**)
     */
    probe cmd__entry(const char *name, Tcl_Size objc, struct Tcl_Obj **objv);
    /*
     *	tcl*:::cmd-return probe
     *	    triggered immediately after commmand execution
     *		arg0: command name			(string)
     *		arg1: return code			(int)
     */
    probe cmd__return(const char *name, int code);
    /*
     *	tcl*:::cmd-result probe
     *	    triggered after cmd-return probe and result processing
     *		arg0: command name			(string)
     *		arg1: return code			(int)
     *		arg2: command result			(string)
     *		arg3: command result object		(Tcl_Obj*)
     */
    probe cmd__result(const char *name, int code, const char *result,
	    struct Tcl_Obj *resultobj);
    /*
     *	tcl*:::cmd-args probe
     *	    triggered before cmd-entry probe, gives access to string
     *	    representation of command arguments
     *		arg0: command name			(string)
     *		arg1-arg9: command arguments or NULL	(strings)
     */
    probe cmd__args(const char *name, const char *arg1, const char *arg2,
	    const char *arg3, const char *arg4, const char *arg5,
	    const char *arg6, const char *arg7, const char *arg8,
	    const char *arg9);
    /*
     *	tcl*:::cmd-info probe
     *	    triggered before cmd-entry probe, gives access to TIP 280
     *	    information for the command invocation (i.e. [info frame 0])
     *		arg0: TIP 280 cmd			(string)
     *		arg1: TIP 280 type			(string)
     *		arg2: TIP 280 proc			(string)
     *		arg3: TIP 280 file			(string)
     *		arg4: TIP 280 line			(int)
     *		arg5: TIP 280 level			(int)
     *		arg6: TclOO method			(string)
     *		arg7: TclOO class/object		(string)
     */
    probe cmd__info(const char *cmd, const char *type, const char *proc,
	    const char *file, int line, Tcl_Size level, const char *method,
	    const char *class);

    /***************************** inst probes *****************************/
    /*
     *	tcl*:::inst-start probe
     *	    triggered immediately before execution of a bytecode
     *		arg0: bytecode name			(string)
     *		arg1: depth of stack			(Tcl_Size)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    probe inst__start(const char *name, Tcl_Size depth, struct Tcl_Obj **stack);
    /*
     *	tcl*:::inst-done probe
     *	    triggered immediately after execution of a bytecode
     *		arg0: bytecode name			(string)
     *		arg1: depth of stack			(Tcl_Size)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    probe inst__done(const char *name, Tcl_Size depth, struct Tcl_Obj **stack);

    /***************************** obj probes ******************************/
    /*
     *	tcl*:::obj-create probe
     *	    triggered immediately after a new Tcl_Obj has been created
     *		arg0: object created			(Tcl_Obj*)
     */
    probe obj__create(struct Tcl_Obj* obj);
    /*
     *	tcl*:::obj-free probe
     *	    triggered immediately before a Tcl_Obj is freed
     *		arg0: object to be freed		(Tcl_Obj*)
     */
    probe obj__free(struct Tcl_Obj* obj);

    /***************************** tcl probes ******************************/
    /*
     *	tcl*:::tcl-probe probe
     *	    triggered when the ::tcl::dtrace command is called
     *		arg0-arg9: command arguments		(strings)
     */
    probe tcl__probe(const char *arg0, const char *arg1, const char *arg2,
	    const char *arg3, const char *arg4, const char *arg5,
	    const char *arg6, const char *arg7, const char *arg8,
	    const char *arg9);
};

/*
 * Tcl types and constants for use in DTrace scripts
 */

typedef struct Tcl_ObjType {
    const char *name;
    void *freeIntRepProc;
    void *dupIntRepProc;
    void *updateStringProc;
    void *setFromAnyProc;
    size_t version;
    void *lengthProc;
    void *indexProc;
    void *sliceProc;
    void *reverseProc;
    void *getElementsProc;
    void *setElementProc;
    void *replaceProc;
    void *inOperProc;
} Tcl_ObjType;

struct Tcl_Obj {
    Tcl_Size refCount;