On Tue, Mar 08, 2005 at 03:05:16PM -0800, Michael G Schwern wrote: > > A singleton is a class that only ever has 1 instance in existence. If there > > can be multiple instances of TB::Counter or TB::Run then by definition > > neither of them are singletons. Conversely if there is only ever 1 instance > > of the Test::Builder class, as chromatic said in his reply, then it is a > > singleton. > > I never worried too much about definitions. > > Point is, normally there's one and only one TB::Counter object floating > around but if you really need to you can make another.
That's what I had hoped for, just those pesky definitions mad me think it was otherwise. > > How can I do that without a global variable? > > An excellent question. It may have to be: > > local $tb->{Level} = $tb->{Level} + 1; > > because local doesn't work on accessors. However localizing hash keys is > its own special layer of hell. Except that involves finding Test::More's $tb from the outside which is probably held in a lexically scoped variable (for good reason). Even if you changed this, going back to the original more complicated problem, imagine Test::AllArray has it's own $tb with it's own default level, how does Test::More's $tb find this when it needs to calculate the current total level. I think this fundamentally requires a global variable. The goal is to find out when did we leave the script and enter Test land. We don't necessarily have to do it by manually tracking levels. If every externally callable test function does local $Entered = $Entered || current_level() at the start. This sounds painful but it can all be handled automagically - bsaically have something wrap all the subs in the package in something like sub { local $Entered = $Entered || current_level(); &$orig(@_); } then any $tb can easily find where we entered Test land. An alternative would to let TB default to assuming that we're only 1 level away but if it finds something in $Entered it will use that instead. Then you could leave most of the functions unwrapped and just wrap functions that call other functions. Plus, accidentally wrapping a function that didn't need it would do no harm. If a test testing module wanted to temporarily pretend that we're entering Test land for the first time it can just do local $Entered. Recording the entry level directly might even be better than recording offsets and calculating the level. I can think of strange situations involving passing subrefs to other modules where you basically have no idea by how much you should be increase $Level. I can't think of any time I'd want to do that in a test module but who knows what someone else would want to do, F