diff options
Diffstat (limited to 'generic/tclTest.c')
| -rw-r--r-- | generic/tclTest.c | 127 | 
1 files changed, 122 insertions, 5 deletions
| diff --git a/generic/tclTest.c b/generic/tclTest.c index 5d65b36..3db70fc 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -222,6 +222,7 @@ static Tcl_ObjCmdProc2	TestbytestringObjCmd;  static Tcl_ObjCmdProc2	TestsetbytearraylengthObjCmd;  static Tcl_ObjCmdProc2	TestpurebytesobjObjCmd;  static Tcl_ObjCmdProc2	TeststringbytesObjCmd; +static Tcl_ObjCmdProc	Testutf16stringObjCmd;  static Tcl_CmdProc	TestcmdinfoCmd;  static Tcl_CmdProc	TestcmdtokenCmd;  static Tcl_CmdProc	TestcmdtraceCmd; @@ -341,6 +342,7 @@ static Tcl_ObjCmdProc2	TestInterpResolverCmd;  #if defined(HAVE_CPUID) && !defined(MAC_OSX_TCL)  static Tcl_ObjCmdProc2	TestcpuidCmd;  #endif +static Tcl_ObjCmdProc	TestApplyLambdaObjCmd;  static const Tcl_Filesystem testReportingFilesystem = {      "reporting", @@ -560,6 +562,7 @@ Tcltest_Init(      Tcl_CreateObjCommand2(interp, "testsetbytearraylength", TestsetbytearraylengthObjCmd, NULL, NULL);      Tcl_CreateObjCommand2(interp, "testbytestring", TestbytestringObjCmd, NULL, NULL);      Tcl_CreateObjCommand2(interp, "teststringbytes", TeststringbytesObjCmd, NULL, NULL); +    Tcl_CreateObjCommand2(interp, "testutf16string", Testutf16stringObjCmd, NULL, NULL);      Tcl_CreateObjCommand2(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,  	    NULL, NULL);      Tcl_CreateObjCommand2(interp, "testfilesystem", TestFilesystemObjCmd, @@ -713,6 +716,8 @@ Tcltest_Init(  	    NULL, NULL);      Tcl_CreateObjCommand2(interp, "testsetencpath", TestsetencpathObjCmd,  	    NULL, NULL); +    Tcl_CreateObjCommand(interp, "testapplylambda", TestApplyLambdaObjCmd, +	    NULL, NULL);      if (TclObjTest_Init(interp) != TCL_OK) {  	return TCL_ERROR; @@ -1114,10 +1119,6 @@ TestcmdinfoCmd(  	info.clientData = (void *) "new_command_data";  	info.objProc = NULL;  	info.objClientData = NULL; -#if TCL_MAJOR_VERSION > 8 || defined(TCL_NO_DEPRECATED) -	info.objProc2 = NULL; -	info.objClientData2 = NULL; -#endif  	info.deleteProc = CmdDelProc2;  	info.deleteData = (void *) "new_delete_data";  	if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) { @@ -5185,6 +5186,43 @@ TestbytestringObjCmd(  /*   *----------------------------------------------------------------------   * + * Testutf16stringObjCmd -- + * + *	This specifically tests the Tcl_GetUnicode and Tcl_NewUnicodeObj + *	C functions which broke in Tcl 8.7 and were undetected by the + *      existing test suite. Bug [b79df322a9] + * + * Results: + *	Returns the TCL_OK result code. + * + * Side effects: + *	None. + * + *---------------------------------------------------------------------- + */ + +static int +Testutf16stringObjCmd( +    TCL_UNUSED(void *), +    Tcl_Interp *interp,		/* Current interpreter. */ +    size_t objc,			/* Number of arguments. */ +    Tcl_Obj *const objv[])	/* The argument objects. */ +{ +    const unsigned short *p; + +    if (objc != 2) { +	Tcl_WrongNumArgs(interp, 1, objv, "string"); +	return TCL_ERROR; +    } + +    p = Tcl_GetUnicode(objv[1]); +    Tcl_SetObjResult(interp, Tcl_NewUnicodeObj(p, -1)); +    return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + *   * TestsetCmd --   *   *	Implements the "testset{err,noerr}" cmds that are used when testing @@ -8091,7 +8129,85 @@ TestInterpResolverCmd(      }      return TCL_OK;  } - + +/* + *------------------------------------------------------------------------ + * + * TestApplyLambdaObjCmd -- + * + *	Implements the Tcl command testapplylambda. This tests the apply + *	implementation handling of a lambda where the lambda has a list + *	internal representation where the second element's internal + *	representation is already a byte code object. + * + * Results: + *	TCL_OK    - Success. Caller should check result is 42 + *	TCL_ERROR - Error. + * + * Side effects: + *	In the presence of the apply bug, may panic. Otherwise + *	Interpreter result holds result or error message. + * + *------------------------------------------------------------------------ + */ +int TestApplyLambdaObjCmd ( +    TCL_UNUSED(void*), +    Tcl_Interp *interp,    /* Current interpreter. */ +    TCL_UNUSED(int),       /* objc. */ +    TCL_UNUSED(Tcl_Obj *const *)) /* objv. */ +{ +    Tcl_Obj *lambdaObjs[2]; +    Tcl_Obj *evalObjs[2]; +    Tcl_Obj *lambdaObj; +    int result; + +    /* Create a lambda {{} {set a 42}} */ +    lambdaObjs[0] = Tcl_NewObj(); /* No parameters */ +    lambdaObjs[1] = Tcl_NewStringObj("set a 42", -1); /* Body */ +    lambdaObj = Tcl_NewListObj(2, lambdaObjs); +    Tcl_IncrRefCount(lambdaObj); + +    /* Create the command "apply {{} {set a 42}" */ +    evalObjs[0] = Tcl_NewStringObj("apply", -1); +    Tcl_IncrRefCount(evalObjs[0]); +    /* +     * NOTE: IMPORTANT TO EXHIBIT THE BUG. We duplicate the lambda because +     * it will get shimmered to a Lambda internal representation but we +     * want to hold on to our list representation. +     */ +    evalObjs[1] = Tcl_DuplicateObj(lambdaObj); +    Tcl_IncrRefCount(evalObjs[1]); + +    /* Evaluate it */ +    result = Tcl_EvalObjv(interp, 2, evalObjs, TCL_EVAL_GLOBAL); +    if (result != TCL_OK) { +	Tcl_DecrRefCount(evalObjs[0]); +	Tcl_DecrRefCount(evalObjs[1]); +	return result; +    } +    /* +     * So far so good. At this point, +     * - evalObjs[1] has an internal representation of Lambda +     * - lambdaObj[1] ({set a 42}) has been shimmered to +     * an internal representation of ByteCode. +     */ +    Tcl_DecrRefCount(evalObjs[1]); /* Don't need this anymore */ +    /* +     * The bug trigger. Repeating the command but: +     *  - we are calling apply with a lambda that is a list (as BEFORE), +     *    BUT +     *  - The body of the lambda (lambdaObjs[1]) ALREADY has internal +     *    representation of ByteCode and thus will not be compiled again +     */ +    evalObjs[1] = lambdaObj; /* lambdaObj already has a ref count so +     				no need for IncrRef */ +    result = Tcl_EvalObjv(interp, 2, evalObjs, TCL_EVAL_GLOBAL); +    Tcl_DecrRefCount(evalObjs[0]); +    Tcl_DecrRefCount(lambdaObj); + +    return result; +} +  /*   * Local Variables:   * mode: c @@ -8101,3 +8217,4 @@ TestInterpResolverCmd(   * indent-tabs-mode: nil   * End:   */ + | 
