Index: TODO =================================================================== diff -u -r29ed0c8902296dbea451c12d031cc06b6126dd5b -rcae9407ff24389d6f950a07279adb31750793e02 --- TODO (.../TODO) (revision 29ed0c8902296dbea451c12d031cc06b6126dd5b) +++ TODO (.../TODO) (revision cae9407ff24389d6f950a07279adb31750793e02) @@ -3344,6 +3344,15 @@ - nsf::object::dispatch with plain methodName - nsf::my (mutual exclusive with -local) +- nsf.c: + * change mem-count statistics from per-interp to per-thread + * generalized GetObjectFromCmdTable() to ReverseLookupCmdFromCmdTable() + * changed GetObjectScreenedByCmdName() to GetHiddenObjectFromCmd() + * modularized interp.test to locate potential problems faster + * partly simplified interp.test syntactically + * deacivated a few tests in interp.test for the time being + (runs commands after finalize) + TODO: - private: * make it mutual exclusive with protected. Index: generic/nsf.c =================================================================== diff -u -rd72a757e0aa13c9e34e5e8d284a6a3a833b9f6e6 -rcae9407ff24389d6f950a07279adb31750793e02 --- generic/nsf.c (.../nsf.c) (revision d72a757e0aa13c9e34e5e8d284a6a3a833b9f6e6) +++ generic/nsf.c (.../nsf.c) (revision cae9407ff24389d6f950a07279adb31750793e02) @@ -223,8 +223,9 @@ static NsfObject *GetObjectFromString(Tcl_Interp *interp, CONST char *name); static NsfClass *GetClassFromString(Tcl_Interp *interp, CONST char *name); static int GetClassFromObj(Tcl_Interp *interp, register Tcl_Obj *objPtr, NsfClass **clPtr, int withUnknown); -static NsfObject *GetObjectScreenedByCmdName(Tcl_Interp *interp, Tcl_Command cmdPtr); -static NsfObject *GetObjectFromCmdTable(Tcl_Interp *interp, Tcl_Command searchCmdPtr, Tcl_HashTable *hTablePtr, CONST char **key); +static NsfObject *GetHiddenObjectFromCmd(Tcl_Interp *interp, Tcl_Command cmdPtr); +static int ReverseLookupCmdFromCmdTable(Tcl_Interp *interp /* needed? */, Tcl_Command searchCmdPtr, + Tcl_HashTable *cmdTablePtr); static void GetAllInstances(Tcl_Interp *interp, Tcl_HashTable *destTablePtr, NsfClass *startClass); NSF_INLINE static Tcl_Command FindMethod(Tcl_Namespace *nsPtr, CONST char *methodName); @@ -2588,10 +2589,7 @@ * destructors, to have the objects marked with NSF_DESTROY_CALLED). */ if (object == NULL) { - Tcl_Command objectCmdPtr; - - objectCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); - object = GetObjectScreenedByCmdName(interp, objectCmdPtr); + object = GetHiddenObjectFromCmd(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); } /*fprintf(stderr, "key = %s %p %d\n", @@ -2618,11 +2616,9 @@ * the objects marked with NSF_DESTROY_CALLED). */ if (cl == NULL) { - Tcl_Command objectCmdPtr; - NsfObject *hiddenObject; - - objectCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); - hiddenObject = GetObjectScreenedByCmdName(interp, objectCmdPtr); + NsfObject *hiddenObject = + GetHiddenObjectFromCmd(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); + cl = hiddenObject && NsfObjectIsClass(hiddenObject) ? (NsfClass *)hiddenObject : NULL; } @@ -4297,11 +4293,11 @@ /* *---------------------------------------------------------------------- - * GetObjectFromCmdTable -- + * ReverseLookupCmdFromCmdTable -- * * Allows for looking up objects in command tables (e.g., namespace cmd * tables, the interp's hidden cmd table) based on their command pointer - * (rather than their command name key). + * (rather than their command name). * * Results: * NsfObject* or NULL @@ -4312,38 +4308,36 @@ *---------------------------------------------------------------------- */ -static NsfObject * -GetObjectFromCmdTable(Tcl_Interp *interp /* needed? */, Tcl_Command searchCmdPtr, - Tcl_HashTable *hTablePtr, CONST char **key) { +static int +ReverseLookupCmdFromCmdTable(Tcl_Interp *interp /* needed? */, Tcl_Command searchCmdPtr, + Tcl_HashTable *cmdTablePtr) { Tcl_HashSearch search; Tcl_HashEntry *hPtr; - Tcl_Command needleCmdPtr; - if (searchCmdPtr == NULL || hTablePtr == NULL) return NULL; - for (hPtr = Tcl_FirstHashEntry(hTablePtr, &search); + assert(searchCmdPtr); + assert(cmdTablePtr); + + for (hPtr = Tcl_FirstHashEntry(cmdTablePtr, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - needleCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); + Tcl_Command needleCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); + if (needleCmdPtr == searchCmdPtr) { - if (key != NULL) { - *key = (char *)Tcl_GetHashKey(hTablePtr, hPtr); - } - return needleCmdPtr && Tcl_Command_objProc(needleCmdPtr) == NsfObjDispatch ? - (NsfObject *)Tcl_Command_objClientData(needleCmdPtr) : NULL; + return 1; } } - return NULL; + return 0; } /* *---------------------------------------------------------------------- - * GetObjectScreenedByCmdName -- + * GetHiddenObjectFromCmd -- * - * Provides for a reverse lookup of *hidden* object structures based on - * their commands. This helper is needed for handling hidden and - * re-exposed objects during the shutdown and the cleanup of object - * systems. See GetAllInstances(), ObjectSystemsCleanup(), and - * FreeAllNsfObjectsAndClasses() + * Obtains a hidden object for a specified cmd. The function uses a reverse + * lookup of *hidden* object structures based on their commands. This + * helper is needed for handling hidden and re-exposed objects during the + * shutdown and the cleanup of object systems. See GetAllInstances(), + * ObjectSystemsCleanup(), and FreeAllNsfObjectsAndClasses() * * Results: * NsfObject* or NULL @@ -4355,33 +4349,41 @@ */ static NsfObject * -GetObjectScreenedByCmdName(Tcl_Interp *interp, Tcl_Command cmdPtr) { +GetHiddenObjectFromCmd(Tcl_Interp *interp, Tcl_Command cmdPtr) { Interp *iPtr = (Interp *) interp; NsfObject *screenedObject; - CONST char *cmdName; + int found; + assert(cmdPtr); /* * We can provide a shortcut, knowing that a) exposed cmds have an epoch * counter > 0, and b) the commands originating namespace must be the global * one. See also Tcl_HideCommand() and Tcl_ExposeCommand(). */ - if (cmdPtr == NULL || Tcl_Command_cmdEpoch(cmdPtr) == 0 || - ((Command *)cmdPtr)->nsPtr != iPtr->globalNsPtr) return NULL; + if (Tcl_Command_cmdEpoch(cmdPtr) == 0 || + ((Command *)cmdPtr)->nsPtr != iPtr->globalNsPtr) { + return NULL; + } /* - * 1) Reverse lookup object in the interp's hidden command table. We start + * Reverse lookup object in the interp's hidden command table. We start * off with the hidden cmds as we suspect their number being smaller than * the re-exposed ones, living in the global namespace */ - screenedObject = GetObjectFromCmdTable(interp, cmdPtr, iPtr->hiddenCmdTablePtr, &cmdName); - if (screenedObject == NULL) { - /* 2) Reverse lookup object in the interp's global command table */ - screenedObject = GetObjectFromCmdTable(interp, cmdPtr, &iPtr->globalNsPtr->cmdTable, &cmdName); + found = ReverseLookupCmdFromCmdTable(interp, cmdPtr, iPtr->hiddenCmdTablePtr); + if (!found) { + /* + * Reverse lookup object in the interp's global command table. Most likely + * needed due to hiding + exposing on a different name. + */ + found = ReverseLookupCmdFromCmdTable(interp, cmdPtr, &iPtr->globalNsPtr->cmdTable); } - + screenedObject = found ? NsfGetObjectFromCmdPtr(cmdPtr) : NULL; + #if !defined(NDEBUG) if (screenedObject) { - fprintf(stderr, "SCREENED OBJECT %s found: object %p (%s) cmd %p\n", cmdName, screenedObject, + fprintf(stderr, "SCREENED OBJECT %s found: object %p (%s) cmd %p\n", + Tcl_GetCommandName(interp, cmdPtr), screenedObject, ObjectName(screenedObject), cmdPtr); } #endif @@ -5821,7 +5823,7 @@ * re-exposed objects during cleanup like ordinary, exposed ones. */ if (object == NULL) { - object = GetObjectScreenedByCmdName(interp, inst->id); + object = GetHiddenObjectFromCmd(interp, inst->id); } assert(object); } @@ -5842,6 +5844,10 @@ * possible. */ if (new) { + /* + * Through the assertion block above, we know already that the entry is + * an exposed or hidden object, we can assiciate the cmd ptr this way. + */ Tcl_SetHashValue(hPtr2, (ClientData)inst->id); } @@ -5921,6 +5927,7 @@ return 1; } } + return 0; } @@ -17060,9 +17067,7 @@ * hide|expose] mechanism. Yet, we want to process them here ... */ if (object == NULL) { - Tcl_Command objectCmdPtr; - objectCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); - object = GetObjectScreenedByCmdName(interp, objectCmdPtr); + object = GetHiddenObjectFromCmd(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); } assert(object); @@ -18360,7 +18365,7 @@ #else flags = NSF_CSC_IMMEDIATE; if (withSystem) {flags |= NSF_CM_SYSTEM_METHOD;} - result = CallMethod(self, interp, methodObj, nobjc+2, nobjv, NSF_CSC_IMMEDIATE); + result = CallMethod(self, interp, methodObj, nobjc+2, nobjv, flags); #endif } return result; @@ -22230,7 +22235,7 @@ NsfObject *object; int deleted = 0; - /*fprintf(stderr, "FreeAllNsfObjectsAndClasses in %p\n", interp);*/ + fprintf(stderr, "FreeAllNsfObjectsAndClasses in %p\n", interp); RUNTIME_STATE(interp)->exitHandlerDestroyRound = NSF_EXITHANDLER_ON_PHYSICAL_DESTROY; @@ -22252,10 +22257,9 @@ * procedure on hidden objects. */ if (object == NULL) { - Tcl_Command objectCmdPtr; - objectCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); - object = GetObjectScreenedByCmdName(interp, objectCmdPtr); + object = GetHiddenObjectFromCmd(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); } + /* delete per-object methods */ if (object && object->nsPtr) { for (hPtr2 = Tcl_FirstHashEntry(Tcl_Namespace_cmdTablePtr(object->nsPtr), &hSrch2); hPtr2; @@ -22321,10 +22325,7 @@ * procedure on hidden objects. */ if (object == NULL) { - Tcl_Command objectCmdPtr; - - objectCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); - object = GetObjectScreenedByCmdName(interp, objectCmdPtr); + object = GetHiddenObjectFromCmd(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); } if (object && !NsfObjectIsClass(object) && !ObjectHasChildren(object)) { @@ -22359,11 +22360,9 @@ * cleanup procedure on hidden objects. */ if (cl == NULL) { - Tcl_Command objectCmdPtr; NsfObject *hiddenObject; - objectCmdPtr = (Tcl_Command)Tcl_GetHashValue(hPtr); - hiddenObject = GetObjectScreenedByCmdName(interp, objectCmdPtr); + hiddenObject = GetHiddenObjectFromCmd(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); cl = hiddenObject && NsfObjectIsClass(hiddenObject) ? (NsfClass *)hiddenObject : NULL; } Index: generic/nsfTrace.c =================================================================== diff -u -reac3a4e34906b1fd7a5b53c331a4368a2cc85ec6 -rcae9407ff24389d6f950a07279adb31750793e02 --- generic/nsfTrace.c (.../nsfTrace.c) (revision eac3a4e34906b1fd7a5b53c331a4368a2cc85ec6) +++ generic/nsfTrace.c (.../nsfTrace.c) (revision cae9407ff24389d6f950a07279adb31750793e02) @@ -106,6 +106,33 @@ #ifdef NSF_MEM_COUNT /* *---------------------------------------------------------------------- + * NsfMemCountGetTable -- + * + * Obtain the hash table structure + * + * Results: + * None. + * + * Side effects: + * Updateing Hash table + * + *---------------------------------------------------------------------- + */ +static Tcl_HashTable * +NsfMemCountGetTable(Tcl_Interp *interp, int **initialized) { + static Tcl_ThreadDataKey memCountTableKey; + static Tcl_ThreadDataKey memCountFlagKey; + Tcl_HashTable *tablePtr; + + tablePtr = (Tcl_HashTable *)Tcl_GetThreadData(&memCountTableKey, sizeof(Tcl_HashTable)); + *initialized = (int *)Tcl_GetThreadData(&memCountFlagKey, sizeof(int)); + + return tablePtr; + //return &RUNTIME_STATE(interp)->memCountTable; +} + +/* + *---------------------------------------------------------------------- * NsfMemCountAlloc -- * * Bookkeeping function for memory und refcount debugging. This function @@ -122,11 +149,16 @@ */ void NsfMemCountAlloc(Tcl_Interp *interp, char *id, void *p) { - int new; + int new, *tableInitialized; NsfMemCounter *entry; - Tcl_HashTable *tablePtr = &RUNTIME_STATE(interp)->memCountTable; + Tcl_HashTable *tablePtr = NsfMemCountGetTable(interp, &tableInitialized); Tcl_HashEntry *hPtr; + if (!*tableInitialized) { + fprintf(stderr, "+++ alloc %s %p\n", id, p); + return; + } + assert(interp); hPtr = Tcl_CreateHashEntry(tablePtr, id, &new); #ifdef NSF_MEM_TRACE @@ -167,8 +199,14 @@ void NsfMemCountFree(Tcl_Interp *interp, char *id, void *p) { NsfMemCounter *entry; - Tcl_HashTable *tablePtr = &RUNTIME_STATE(interp)->memCountTable; + int *tableInitialized; + Tcl_HashTable *tablePtr = NsfMemCountGetTable(interp, &tableInitialized); Tcl_HashEntry *hPtr; + + if (!*tableInitialized) { + fprintf(stderr, "+++ free %s %p\n", id, p); + return; + } #ifdef NSF_MEM_TRACE fprintf(stderr, "+++ free %s %p\n", id, p); #endif @@ -201,9 +239,17 @@ */ void NsfMemCountInit(Tcl_Interp *interp) { - Tcl_HashTable *tablePtr = &RUNTIME_STATE(interp)->memCountTable; + int *tableInitialized; + Tcl_HashTable *tablePtr = NsfMemCountGetTable(interp, &tableInitialized); - Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS); + if (!*tableInitialized) { + Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS); + } + (*tableInitialized) ++; + +#ifdef NSF_MEM_TRACE + fprintf(stderr, "+++ init interp %p count %d\n", interp, *tableInitialized); +#endif } /* @@ -225,32 +271,39 @@ */ void NsfMemCountRelease(Tcl_Interp *interp) { - Tcl_HashTable *tablePtr = &RUNTIME_STATE(interp)->memCountTable; + int *tableInitialized; + Tcl_HashTable *tablePtr = NsfMemCountGetTable(interp, &tableInitialized); Tcl_HashSearch search; Tcl_HashEntry *hPtr; int count = 0; -#if 0 - nsfMemCountInterpCounter--; - if (nsfMemCountInterpCounter != 0) { - return; - } +#ifdef NSF_MEM_TRACE + fprintf(stderr, "+++ release interp %p count %d\n", interp, *tableInitialized); #endif - fprintf(stderr, "******** NSF MEM Count *********\n* count peak\n"); + if (!*tableInitialized) { + fprintf(stderr, "+++ release called on uninitialized/free hash table, interp %p\n", interp); + return; + } - for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; - hPtr = Tcl_NextHashEntry(&search)) { - char *id = Tcl_GetHashKey(tablePtr, hPtr); - NsfMemCounter *entry = (NsfMemCounter*) Tcl_GetHashValue(hPtr); - count += entry->count; - fprintf(stderr, "* %4d %6d %s\n", entry->count, entry->peak, id); - ckfree ((char*) entry); + if (*tableInitialized == 1) { + fprintf(stderr, "******** NSF MEM Count *********\n* count peak\n"); + + for (hPtr = Tcl_FirstHashEntry(tablePtr, &search); hPtr != NULL; + hPtr = Tcl_NextHashEntry(&search)) { + char *id = Tcl_GetHashKey(tablePtr, hPtr); + NsfMemCounter *entry = (NsfMemCounter*) Tcl_GetHashValue(hPtr); + count += entry->count; + fprintf(stderr, "* %4d %6d %s\n", entry->count, entry->peak, id); + ckfree ((char*) entry); + } + + Tcl_DeleteHashTable(tablePtr); + + fprintf(stderr, "******** Count Overall = %d\n", count); } - - Tcl_DeleteHashTable(tablePtr); - - fprintf(stderr, "******** Count Overall = %d\n", count); + + (*tableInitialized) --; } #endif Index: tests/interp.test =================================================================== diff -u -rd72a757e0aa13c9e34e5e8d284a6a3a833b9f6e6 -rcae9407ff24389d6f950a07279adb31750793e02 --- tests/interp.test (.../interp.test) (revision d72a757e0aa13c9e34e5e8d284a6a3a833b9f6e6) +++ tests/interp.test (.../interp.test) (revision cae9407ff24389d6f950a07279adb31750793e02) @@ -10,6 +10,7 @@ # # Create a slave interp for testing # + global i set i [interp create] # @@ -21,9 +22,9 @@ } $i hide foo - ? [list $i eval [list info commands ::nx::Object]] "" + ? {$i eval [list info commands ::nx::Object]} "" $i eval [list package req nx] - ? [list $i eval [list info commands ::nx::Object]] ::nx::Object + ? {$i eval [list info commands ::nx::Object]} ::nx::Object # # Tcl's hiding mechansim only applies to objects/classes in the # top-level namespace. So any non-globally namespaced ones and @@ -59,9 +60,9 @@ return [::nsf::current object]-[:info class]-[::nsf::current class] } }} - ? [list $i eval [list info commands ::o]] ::o - ? [list $i eval [list info commands ::C]] ::C - ? [list $i eval [list info commands ::M]] ::M + ? {$i eval {info commands ::o}} ::o + ? {$i eval {info commands ::C}} ::C + ? {$i eval {info commands ::M}} ::M # # [interp hide] performs a partial and widely silent deletion @@ -74,51 +75,50 @@ # target anymore ... # - ? [list interp hidden $i] "foo" + ? {interp hidden $i} "foo" $i hide o - ? [list interp hidden $i] "foo o" - ? [list $i eval [list ::o]] "invalid command name \"::o\"" - ? [list $i eval [list info commands ::o]] "" + ? {interp hidden $i} "foo o" + ? {$i eval ::o} "invalid command name \"::o\"" + ? {$i eval {info commands ::o}} "" - ? [list interp eval $i [list ::C create ::c]] ::c + ? {interp eval $i {::C create ::c}} ::c # set some relationships to test later ... - ? [list interp eval $i [list ::C mixin add ::M]] ::M - ? [list interp eval $i [list ::C class mixin add ::M]] ::M + ? {interp eval $i {::C mixin add ::M}} ::M + ? {interp eval $i {::C class mixin add ::M}} ::M $i hide C - ? [list interp eval $i [list ::C create ::c2]] {invalid command name "::C"} + ? {interp eval $i {::C create ::c2}} {invalid command name "::C"} # # However, the object structure is effectively preserved within the # object system and object relations are intact, e.g., the object is # still reported as an instance of a class. # - ? [list $i eval [list nx::Object info instances ::o]] "::o" - ? [list interp invokehidden $i o ::nsf::methods::object::info::class] "::nx::Object" - ? [list interp invokehidden $i o info class] "::nx::Object" + ? {$i eval {nx::Object info instances ::o}} "::o" + ? {interp invokehidden $i o ::nsf::methods::object::info::class} "::nx::Object" + ? {interp invokehidden $i o info class} "::nx::Object" - ? [list interp eval $i {c info class}] ::C - ? [list interp eval $i {c info class}] ::C - ? [list interp invokehidden $i C info instances ::c] ::c - ? [list interp invokehidden $i C info mixin classes] ::M + ? {interp eval $i {c info class}} ::C + ? {interp invokehidden $i C info instances ::c} ::c + ? {interp invokehidden $i C info mixin classes} ::M + # Note, for all introspections that do *not* try to convert the # Tcl_Obj into an object or a class, but treat it as a pattern (or # the like) we are fine ... - ? [list $i eval {M info mixinof ::C}] "::C ::C" - ? [list $i eval {M info mixinof -scope class ::C}] "::C" - ? [list $i eval {M info mixinof -scope object ::C}] "::C" + ? {$i eval {M info mixinof ::C}} "::C ::C" + ? {$i eval {M info mixinof -scope class ::C}} "::C" + ? {$i eval {M info mixinof -scope object ::C}} "::C" # dispatch to object-provided method (with the object being hidden) - ? [list interp eval $i {c bar}] OK - + ? {interp eval $i {c bar}} OK # dispatch to class-provided methods (with the class being hidden) - ? [list interp eval $i {c bar}] OK + ? {interp eval $i {c bar}} OK # dispatch to mixed-in methods (which do basic introspection on the hidden object) ... - ? [list interp invokehidden $i C foo] ::C-::nx::Class-::M - ? [list interp eval $i {c foo}] ::c-::C-::M + ? {interp invokehidden $i C foo} ::C-::nx::Class-::M + ? {interp eval $i {c foo}} ::c-::C-::M # # 1) Implicit destruction (through NSF's exit handler) @@ -132,23 +132,43 @@ # interp by using ::nsf::finalize; to do some smoke testing of the # cleanup results. As for the cleanup procedre, this is equivalent # to: interp delete $i + + $i eval {::nsf::finalize} - - ? [list $i eval {interp hidden}] foo - ? [list $i eval [list info commands ::o]] "" - ? [list $i eval [list info commands ::C]] "" - + + # The destructor of e.g. object o sets a global variable with the + # object name. The following test checks therfore, whether the + # destructor was executed. # - # Were the app-level destructors called effectively? + # However, as documented ::nsf::finalize has to be the final nsf cmd + # in an interp. The behavior after finalize is undefined and depends + # in the detail on several compiler flags. For example, when + # MEM_COUNT is activated, a full cleanup us performed by nsf, + # causing the deletion of all variables and cmds. This is necessary + # to ensure a defined situation of the refcounts when for debugging. + # Therefore the following cmds will fail - for the time being + # deactivated. # - ? [list $i eval { info exists ::o }] 1 - ? [list $i eval { set ::o }] "" - ? [list $i eval { info exists ::c }] 1 - ? [list $i eval { set ::c }] ::C - - + if {0} { + ? {$i eval { info exists ::o }} 1 + + ? {$i eval {interp hidden}} foo + ? {$i eval {info commands ::o}} "" + ? {$i eval {info commands ::C}} "" + + # + # Were the app-level destructors called effectively? + # + ? {$i eval { info exists ::o }} 1 + ? {$i eval { set ::o }} "" + ? {$i eval { info exists ::c }} 1 + ? {$i eval { set ::c }} ::C + } interp delete $i +} +nx::Test case hidden-cmds+explicit-delete { + # # 2) Explicit destruction # @@ -187,6 +207,9 @@ [::nsf::object::exists ::o2] }] {{} {} {} 0} +} + +nx::Test case hide-and-re-expose { # # 3) hide and re-expose # @@ -227,18 +250,23 @@ ? [list $i eval {::o foo}] {::o {} ::nx::Object ::nx::Object} $i eval {::nsf::finalize} - - # Was the destructor called? - ? [list interp eval $i {info exists ::o}] 1 - ? [list interp eval $i {set ::o}] 1 - - ? [list interp eval $i { - list [interp hidden] \ - [info commands ::o] - }] {{} {}} "Check cleaned-up state" + # deactivated, SEE above + if {0} { + # Was the destructor called? + ? [list interp eval $i {info exists ::o}] 1 + ? [list interp eval $i {set ::o}] 1 + + ? [list interp eval $i { + list [interp hidden] \ + [info commands ::o] + }] {{} {}} "Check cleaned-up state" + } interp delete $i +} +nx::Test case command-renaming { + # 4) hide/re-expose with "command renaming" set i [interp create] @@ -282,17 +310,23 @@ $i eval {::nsf::finalize} - # Was the destructor called? - ? [list interp eval $i {info exists ::o}] 1 - ? [list interp eval $i {set ::o}] 1 - - ? [list interp eval $i { - list [interp hidden] \ - [info commands ::o] - }] {{} {}} "Check cleaned-up state" - + # deactivated, SEE above + if {0} { + # Was the destructor called? + ? [list interp eval $i {info exists ::o}] 1 + ? [list interp eval $i {set ::o}] 1 + + ? [list interp eval $i { + list [interp hidden] \ + [info commands ::o] + }] {{} {}} "Check cleaned-up state" + } interp delete $i +} + +nx::Test case namespaced-object { + # 5) Rename namespaced object to global one and hide ... set i [interp create] @@ -324,10 +358,16 @@ [::nsf::object::exists ::X] }] {X {} ::X 0} $i eval {::nsf::finalize} - ? [list interp eval $i {info exists ::X}] 1 - ? [list interp eval $i {set ::X}] 1 + # deactivated, SEE above + if {0} { + ? [list interp eval $i {info exists ::X}] 1 + ? [list interp eval $i {set ::X}] 1 + } interp delete $i +} +nx::Test case deletion-order { + # # 6) Deletion order # @@ -354,12 +394,17 @@ $i hide o $i hide C $i eval {::nsf::finalize} - ? [list interp eval $i {info exists ::C}] 1 - ? [list interp eval $i {set ::C}] 1 - ? [list interp eval $i {info exists ::o}] 1 - ? [list interp eval $i {set ::o}] 1 + # deactivated, SEE above + if {0} { + ? [list interp eval $i {info exists ::C}] 1 + ? [list interp eval $i {set ::C}] 1 + ? [list interp eval $i {info exists ::o}] 1 + ? [list interp eval $i {set ::o}] 1 + } interp delete $i +} +nx::Test case error-in-destroy { # 8a) Some stumbling blocks in destructors: [error] in app-level destroy set i [interp create] $i eval {